summaryrefslogtreecommitdiff
path: root/usr/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib')
-rw-r--r--usr/src/lib/libshare/common/libshare.c14
-rw-r--r--usr/src/lib/libshare/common/libshare_zfs.c1
-rw-r--r--usr/src/lib/libshare/common/libsharecore.c11
-rw-r--r--usr/src/lib/libshare/common/scfutil.c25
-rw-r--r--usr/src/lib/libshare/nfs/libshare_nfs.c6
-rw-r--r--usr/src/lib/libshare/smb/libshare_smb.c10
-rw-r--r--usr/src/lib/smbsrv/libmlrpc/common/libmlrpc.h4
-rw-r--r--usr/src/lib/smbsrv/libmlrpc/common/ndr_marshal.c7
-rw-r--r--usr/src/lib/smbsrv/libmlrpc/common/ndr_ops.c14
-rw-r--r--usr/src/lib/smbsrv/libmlrpc/common/ndr_process.c7
-rw-r--r--usr/src/lib/smbsrv/libmlrpc/common/ndr_server.c16
-rw-r--r--usr/src/lib/smbsrv/libmlsvc/Makefile.com12
-rw-r--r--usr/src/lib/smbsrv/libmlsvc/common/libmlsvc.h16
-rw-r--r--usr/src/lib/smbsrv/libmlsvc/common/lsalib.c29
-rw-r--r--usr/src/lib/smbsrv/libmlsvc/common/lsalib.h8
-rw-r--r--usr/src/lib/smbsrv/libmlsvc/common/lsar_clnt.c (renamed from usr/src/lib/smbsrv/libmlsvc/common/lsar_lookup.c)1006
-rw-r--r--usr/src/lib/smbsrv/libmlsvc/common/lsar_open.c223
-rw-r--r--usr/src/lib/smbsrv/libmlsvc/common/lsar_svc.c (renamed from usr/src/lib/smbsrv/libmlsvc/common/mlsvc_lsa.c)189
-rw-r--r--usr/src/lib/smbsrv/libmlsvc/common/mapfile-vers5
-rw-r--r--usr/src/lib/smbsrv/libmlsvc/common/mlsvc_client.c83
-rw-r--r--usr/src/lib/smbsrv/libmlsvc/common/mlsvc_util.c54
-rw-r--r--usr/src/lib/smbsrv/libmlsvc/common/samlib.c2
-rw-r--r--usr/src/lib/smbsrv/libmlsvc/common/samr_clnt.c (renamed from usr/src/lib/smbsrv/libmlsvc/common/samr_open.c)502
-rw-r--r--usr/src/lib/smbsrv/libmlsvc/common/samr_lookup.c524
-rw-r--r--usr/src/lib/smbsrv/libmlsvc/common/samr_svc.c (renamed from usr/src/lib/smbsrv/libmlsvc/common/mlsvc_sam.c)84
-rw-r--r--usr/src/lib/smbsrv/libmlsvc/common/smb_autohome.c10
-rw-r--r--usr/src/lib/smbsrv/libmlsvc/common/smb_logon.c3
-rw-r--r--usr/src/lib/smbsrv/libmlsvc/common/smb_share.c35
-rw-r--r--usr/src/lib/smbsrv/libmlsvc/common/srvsvc_sd.c41
-rw-r--r--usr/src/lib/smbsrv/libmlsvc/common/srvsvc_svc.c47
-rw-r--r--usr/src/lib/smbsrv/libsmb/common/libsmb.h15
-rw-r--r--usr/src/lib/smbsrv/libsmb/common/mapfile-vers9
-rw-r--r--usr/src/lib/smbsrv/libsmb/common/smb_api_door_calls.c137
-rw-r--r--usr/src/lib/smbsrv/libsmb/common/smb_door_encdec.c56
-rw-r--r--usr/src/lib/smbsrv/libsmb/common/smb_lgrp.c72
-rw-r--r--usr/src/lib/smbsrv/libsmb/common/smb_pwdutil.c10
-rw-r--r--usr/src/lib/smbsrv/libsmb/common/smb_sd.c3
-rw-r--r--usr/src/lib/smbsrv/libsmb/common/smb_util.c243
-rw-r--r--usr/src/lib/smbsrv/libsmbns/common/smbns_ads.c76
39 files changed, 2147 insertions, 1462 deletions
diff --git a/usr/src/lib/libshare/common/libshare.c b/usr/src/lib/libshare/common/libshare.c
index 6af47e38c6..d8989a70ce 100644
--- a/usr/src/lib/libshare/common/libshare.c
+++ b/usr/src/lib/libshare/common/libshare.c
@@ -727,11 +727,13 @@ sa_optionset_name(sa_optionset_t optionset, char *oname, size_t len, char *id)
} else {
char *index;
index = get_node_attr((void *)parent, "id");
- if (index != NULL)
+ if (index != NULL) {
len = snprintf(oname, len, "%s_%s_%s", id,
proto ? proto : "default", index);
- else
+ sa_free_attr_string(index);
+ } else {
len = 0;
+ }
}
if (proto != NULL)
@@ -1387,7 +1389,6 @@ mark_excluded_protos(sa_group_t group, xmlNodePtr share, uint64_t flags)
if (value == NULL)
continue;
features = sa_proto_get_featureset(value);
- sa_free_attr_string(value);
if (!(features & flags)) {
(void) strlcat(exclude_list, sep,
sizeof (exclude_list));
@@ -1395,6 +1396,7 @@ mark_excluded_protos(sa_group_t group, xmlNodePtr share, uint64_t flags)
sizeof (exclude_list));
sep = ",";
}
+ sa_free_attr_string(value);
}
if (exclude_list[0] != '\0')
(void) xmlSetProp(share, (xmlChar *)"exclude",
@@ -2043,7 +2045,7 @@ get_node_attr(void *nodehdl, char *tag)
}
/*
- * get_node_attr(node, tag)
+ * set_node_attr(node, tag)
*
* Set the specified tag(attribute) to the specified value This is
* used internally by a number of attribute oriented functions. It
@@ -2897,6 +2899,8 @@ sa_create_security(sa_group_t group, char *sectype, char *proto)
}
}
}
+ if (id != NULL)
+ sa_free_attr_string(id);
if (groupname != NULL)
sa_free_attr_string(groupname);
return (security);
@@ -3109,6 +3113,8 @@ sa_set_prop_by_prop(sa_optionset_t optionset, sa_group_t group,
(void) sa_security_name(optionset,
oname, sizeof (oname), id);
ret = sa_start_transaction(scf_handle, oname);
+ if (id != NULL)
+ sa_free_attr_string(id);
}
if (ret == SA_OK) {
switch (type) {
diff --git a/usr/src/lib/libshare/common/libshare_zfs.c b/usr/src/lib/libshare/common/libshare_zfs.c
index 7e461ba3b7..5adef70b4c 100644
--- a/usr/src/lib/libshare/common/libshare_zfs.c
+++ b/usr/src/lib/libshare/common/libshare_zfs.c
@@ -990,6 +990,7 @@ add_resources(sa_share_t share, char *opt)
newopt = calloc(1, size);
if (newopt != NULL)
(void) snprintf(newopt, size, "%s,name=%s", opt, name);
+ sa_free_attr_string(name);
free(opt);
opt = newopt;
propstr = sa_proto_legacy_format("smb", resource, 0);
diff --git a/usr/src/lib/libshare/common/libsharecore.c b/usr/src/lib/libshare/common/libsharecore.c
index 72d3420e1c..18e5f3c793 100644
--- a/usr/src/lib/libshare/common/libsharecore.c
+++ b/usr/src/lib/libshare/common/libsharecore.c
@@ -410,7 +410,7 @@ adddfsentry(xfs_sharelist_t *list, sa_share_t share, char *proto)
if (item != NULL) {
parent = sa_get_parent_group(share);
groupname = sa_get_group_attr(parent, "name");
- if (strcmp(groupname, "default") == 0) {
+ if (groupname != NULL && strcmp(groupname, "default") == 0) {
sa_free_attr_string(groupname);
groupname = NULL;
}
@@ -691,11 +691,15 @@ sa_update_legacy(sa_share_t share, char *proto)
* set or the type is not "transient".
*/
if (persist == NULL || strcmp(persist, "transient") != 0) {
+ path = sa_get_share_attr(share, "path");
+ if (path == NULL) {
+ ret = SA_NO_MEMORY;
+ goto out;
+ }
dfstab = open_dfstab(SA_LEGACY_DFSTAB);
if (dfstab != NULL) {
(void) setvbuf(dfstab, NULL, _IOLBF, BUFSIZ * 8);
sablocksigs(&old);
- path = sa_get_share_attr(share, "path");
(void) lockf(fileno(dfstab), F_LOCK, 0);
list = getdfstab(dfstab);
rewind(dfstab);
@@ -708,7 +712,6 @@ sa_update_legacy(sa_share_t share, char *proto)
(void) fsync(fileno(dfstab));
saunblocksigs(&old);
(void) fclose(dfstab);
- sa_free_attr_string(path);
if (list != NULL)
dfs_free_list(list);
} else {
@@ -717,7 +720,9 @@ sa_update_legacy(sa_share_t share, char *proto)
else
ret = SA_CONFIG_ERR;
}
+ sa_free_attr_string(path);
}
+out:
if (persist != NULL)
sa_free_attr_string(persist);
return (ret);
diff --git a/usr/src/lib/libshare/common/scfutil.c b/usr/src/lib/libshare/common/scfutil.c
index f5fabad540..21395d0731 100644
--- a/usr/src/lib/libshare/common/scfutil.c
+++ b/usr/src/lib/libshare/common/scfutil.c
@@ -20,12 +20,10 @@
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/* helper functions for using libscf with sharemgr */
#include <libscf.h>
@@ -1585,7 +1583,7 @@ sa_set_resource_property(scfutilhandle_t *handle, sa_share_t share)
valstr ? valstr : "");
else
(void) snprintf(propstr, strsize, "%s:%s:%s",
- idstr ? idstr : "", valstr ? valstr : "",
+ idstr, valstr ? valstr : "",
description ? description : "");
if (scf_value_set_astring(value, propstr) != 0) {
ret = SA_SYSTEM_ERR;
@@ -1604,16 +1602,29 @@ sa_set_resource_property(scfutilhandle_t *handle, sa_share_t share)
free(propstr);
}
err:
- if (valstr != NULL)
+ if (valstr != NULL) {
sa_free_attr_string(valstr);
- if (idstr != NULL)
+ valstr = NULL;
+ }
+ if (idstr != NULL) {
sa_free_attr_string(idstr);
- if (description != NULL)
+ idstr = NULL;
+ }
+ if (description != NULL) {
sa_free_share_description(description);
+ description = NULL;
+ }
}
/* the entry is in the transaction */
entry = NULL;
+ if (valstr != NULL)
+ sa_free_attr_string(valstr);
+ if (idstr != NULL)
+ sa_free_attr_string(idstr);
+ if (description != NULL)
+ sa_free_share_description(description);
+
if (ret == SA_SYSTEM_ERR) {
switch (scf_error()) {
case SCF_ERROR_PERMISSION_DENIED:
diff --git a/usr/src/lib/libshare/nfs/libshare_nfs.c b/usr/src/lib/libshare/nfs/libshare_nfs.c
index b71df49804..8007ab2466 100644
--- a/usr/src/lib/libshare/nfs/libshare_nfs.c
+++ b/usr/src/lib/libshare/nfs/libshare_nfs.c
@@ -1014,7 +1014,8 @@ fill_export_from_optionset(struct exportdata *export, sa_optionset_t optionset)
/* have a syntactic error */
(void) printf(dgettext(TEXT_DOMAIN,
"NFS: unrecognized option %s=%s\n"),
- name, value != NULL ? value : "");
+ name != NULL ? name : "",
+ value != NULL ? value : "");
break;
}
if (name != NULL)
@@ -1841,7 +1842,7 @@ nfs_enable_share(sa_share_t share)
prop != NULL && i < num_secinfo;
prop = sa_get_next_property(prop), i++) {
char *sectype;
- sectype = sa_get_property_attr(prop, "type");
+ sectype = sa_get_property_attr(prop, "type");
/*
* if sectype is NULL, we probably
* have a memory problem and can't get
@@ -3023,6 +3024,7 @@ nfs_minmax_check(int index, int value)
OPT_CMP_GE) {
ret = value >= val ? B_TRUE : B_FALSE;
}
+ sa_free_attr_string(pval);
}
}
}
diff --git a/usr/src/lib/libshare/smb/libshare_smb.c b/usr/src/lib/libshare/smb/libshare_smb.c
index 2b72fe919a..b6c5417c19 100644
--- a/usr/src/lib/libshare/smb/libshare_smb.c
+++ b/usr/src/lib/libshare/smb/libshare_smb.c
@@ -563,7 +563,8 @@ smb_disable_resource(sa_resource_t resource)
if (smb_isonline()) {
res = smb_share_delete(rname);
- if (res != NERR_Success) {
+ if (res != NERR_Success &&
+ res != NERR_NetNameNotFound) {
sa_free_attr_string(rname);
return (SA_CONFIG_ERR);
}
@@ -1775,8 +1776,9 @@ smb_parse_optstring(sa_group_t group, char *options)
"prefix", prefix);
}
}
- name = fix_resource_name((sa_share_t)group,
- value, prefix);
+ if (prefix != NULL)
+ name = fix_resource_name(
+ (sa_share_t)group, value, prefix);
if (name != NULL) {
resource = sa_add_resource(
(sa_share_t)group, name,
@@ -1981,6 +1983,8 @@ smb_rename_resource(sa_handle_t handle, sa_resource_t resource, char *newname)
err = smb_share_rename(oldname, newname);
+ sa_free_attr_string(oldname);
+
/* improve error values somewhat */
switch (err) {
case NERR_Success:
diff --git a/usr/src/lib/smbsrv/libmlrpc/common/libmlrpc.h b/usr/src/lib/smbsrv/libmlrpc/common/libmlrpc.h
index f832e1d0cf..cc97e6046e 100644
--- a/usr/src/lib/smbsrv/libmlrpc/common/libmlrpc.h
+++ b/usr/src/lib/smbsrv/libmlrpc/common/libmlrpc.h
@@ -457,6 +457,7 @@ typedef struct ndr_client {
ndr_binding_t *binding_list;
ndr_binding_t binding_pool[NDR_N_BINDING_POOL];
+ boolean_t nonull;
boolean_t heap_preserved;
ndr_heap_t *heap;
ndr_stream_t *recv_nds;
@@ -470,7 +471,6 @@ typedef struct ndr_handle {
ndr_hdid_t nh_id;
struct ndr_handle *nh_next;
int nh_fid;
- int nh_remote_os;
const ndr_service_t *nh_svc;
ndr_client_t *nh_clnt;
void *nh_data;
@@ -488,7 +488,7 @@ typedef struct ndr_buf {
} ndr_buf_t;
/* ndr_ops.c */
-void nds_initialize(ndr_stream_t *, unsigned, int, ndr_heap_t *);
+int nds_initialize(ndr_stream_t *, unsigned, int, ndr_heap_t *);
void nds_finalize(ndr_stream_t *, ndr_fraglist_t *);
void nds_destruct(ndr_stream_t *);
void nds_show_state(ndr_stream_t *);
diff --git a/usr/src/lib/smbsrv/libmlrpc/common/ndr_marshal.c b/usr/src/lib/smbsrv/libmlrpc/common/ndr_marshal.c
index abed01bf2f..2c0fc3e478 100644
--- a/usr/src/lib/smbsrv/libmlrpc/common/ndr_marshal.c
+++ b/usr/src/lib/smbsrv/libmlrpc/common/ndr_marshal.c
@@ -138,8 +138,11 @@ ndr_buf_decode(ndr_buf_t *nbuf, unsigned opnum, const char *data,
else
pdu_size_hint = datalen;
- nds_initialize(&nbuf->nb_nds, pdu_size_hint, NDR_MODE_BUF_DECODE,
+ rc = nds_initialize(&nbuf->nb_nds, pdu_size_hint, NDR_MODE_BUF_DECODE,
nbuf->nb_heap);
+ if (NDR_DRC_IS_FAULT(rc))
+ return (rc);
+
bcopy(data, nbuf->nb_nds.pdu_base_addr, datalen);
rc = ndr_decode_hdr_common(&nbuf->nb_nds, &hdr);
@@ -147,7 +150,7 @@ ndr_buf_decode(ndr_buf_t *nbuf, unsigned opnum, const char *data,
return (rc);
if (!NDR_IS_SINGLE_FRAG(hdr.pfc_flags))
- return (rc);
+ return (NDR_DRC_FAULT_DECODE_FAILED);
rc = ndr_encode_decode_common(&nbuf->nb_nds, opnum, nbuf->nb_ti,
result);
diff --git a/usr/src/lib/smbsrv/libmlrpc/common/ndr_ops.c b/usr/src/lib/smbsrv/libmlrpc/common/ndr_ops.c
index 2d4573b613..25f43111db 100644
--- a/usr/src/lib/smbsrv/libmlrpc/common/ndr_ops.c
+++ b/usr/src/lib/smbsrv/libmlrpc/common/ndr_ops.c
@@ -121,7 +121,7 @@ nds_bswap(void *srcbuf, void *dstbuf, size_t len)
* operations and the reference to the heap. An external heap is provided
* to the stream, rather than each stream creating its own heap.
*/
-void
+int
nds_initialize(ndr_stream_t *nds, unsigned pdu_size_hint,
int composite_op, ndr_heap_t *heap)
{
@@ -133,11 +133,16 @@ nds_initialize(ndr_stream_t *nds, unsigned pdu_size_hint,
bzero(nds, sizeof (*nds));
if (pdu_size_hint > NDR_PDU_MAX_SIZE)
- return;
+ return (0);
size = (pdu_size_hint == 0) ? NDR_PDU_BLOCK_SIZE : pdu_size_hint;
- nds->pdu_base_addr = malloc(size);
- assert(nds->pdu_base_addr);
+
+ if ((nds->pdu_base_addr = malloc(size)) == NULL) {
+ nds->error = NDR_ERR_MALLOC_FAILED;
+ nds->error_ref = __LINE__;
+ NDS_TATTLE_ERROR(nds, NULL, NULL);
+ return (NDR_DRC_FAULT_OUT_OF_MEMORY);
+ }
nds->pdu_max_size = size;
nds->pdu_size = 0;
@@ -150,6 +155,7 @@ nds_initialize(ndr_stream_t *nds, unsigned pdu_size_hint,
nds->dir = NDR_MODE_TO_DIR(composite_op);
nds->outer_queue_tailp = &nds->outer_queue_head;
+ return (0);
}
void
diff --git a/usr/src/lib/smbsrv/libmlrpc/common/ndr_process.c b/usr/src/lib/smbsrv/libmlrpc/common/ndr_process.c
index af76a0a08c..ebc66c0810 100644
--- a/usr/src/lib/smbsrv/libmlrpc/common/ndr_process.c
+++ b/usr/src/lib/smbsrv/libmlrpc/common/ndr_process.c
@@ -1189,8 +1189,11 @@ ndr_outer_string(ndr_ref_t *outer_ref)
* size_is is the number of characters in the
* (multibyte) string, including the null.
*/
- size_is = (smb_wcequiv_strlen(valp) /
- sizeof (smb_wchar_t)) + 1;
+ size_is = smb_wcequiv_strlen(valp) /
+ sizeof (smb_wchar_t);
+
+ if (!(nds->flags & NDS_F_NONULL))
+ ++size_is;
if (size_is > NDR_STRING_MAX) {
NDR_SET_ERROR(outer_ref, NDR_ERR_STRLEN);
diff --git a/usr/src/lib/smbsrv/libmlrpc/common/ndr_server.c b/usr/src/lib/smbsrv/libmlrpc/common/ndr_server.c
index 0c2dde8be2..93070966f5 100644
--- a/usr/src/lib/smbsrv/libmlrpc/common/ndr_server.c
+++ b/usr/src/lib/smbsrv/libmlrpc/common/ndr_server.c
@@ -217,6 +217,7 @@ ndr_pipe_transact(ndr_pipe_t *np)
ndr_stream_t *send_nds;
char *data;
int datalen;
+ int rc;
data = np->np_buf;
datalen = np->np_uio.uio_offset;
@@ -235,7 +236,12 @@ ndr_pipe_transact(ndr_pipe_t *np)
}
recv_nds = &mxa->recv_nds;
- nds_initialize(recv_nds, datalen, NDR_MODE_CALL_RECV, mxa->heap);
+ rc = nds_initialize(recv_nds, datalen, NDR_MODE_CALL_RECV, mxa->heap);
+ if (rc != 0) {
+ ndr_heap_destroy(mxa->heap);
+ free(mxa);
+ return (ENOMEM);
+ }
/*
* Copy the input data and reset the input stream.
@@ -244,7 +250,13 @@ ndr_pipe_transact(ndr_pipe_t *np)
ndr_pipe_rewind(np);
send_nds = &mxa->send_nds;
- nds_initialize(send_nds, 0, NDR_MODE_RETURN_SEND, mxa->heap);
+ rc = nds_initialize(send_nds, 0, NDR_MODE_RETURN_SEND, mxa->heap);
+ if (rc != 0) {
+ nds_destruct(&mxa->recv_nds);
+ ndr_heap_destroy(mxa->heap);
+ free(mxa);
+ return (ENOMEM);
+ }
(void) ndr_svc_process(mxa);
diff --git a/usr/src/lib/smbsrv/libmlsvc/Makefile.com b/usr/src/lib/smbsrv/libmlsvc/Makefile.com
index c10cab0b67..af744ee14c 100644
--- a/usr/src/lib/smbsrv/libmlsvc/Makefile.com
+++ b/usr/src/lib/smbsrv/libmlsvc/Makefile.com
@@ -33,14 +33,12 @@ OBJS_COMMON = \
eventlog_svc.o \
eventlog_syslog.o \
lsalib.o \
- lsar_lookup.o \
- lsar_open.o \
+ lsar_clnt.o \
+ lsar_svc.o \
mlsvc_client.o \
mlsvc_domain.o \
mlsvc_init.o \
- mlsvc_lsa.o \
mlsvc_netr.o \
- mlsvc_sam.o \
mlsvc_util.o \
mlsvc_wkssvc.o \
msgsvc_svc.o \
@@ -48,8 +46,8 @@ OBJS_COMMON = \
netr_auth.o \
netr_logon.o \
samlib.o \
- samr_open.o \
- samr_lookup.o \
+ samr_clnt.o \
+ samr_svc.o \
smb_autohome.o \
smb_logon.o \
smb_share.o \
@@ -84,7 +82,7 @@ INCS += -I$(SRC)/common/smbsrv
LDLIBS += $(MACH_LDLIBS)
LDLIBS += -lmlrpc -lsmbrdr -lsmb -lsmbns -lshare -lresolv -lnsl -lpkcs11 -lscf \
- -lnvpair -luutil -lzfs -lc
+ -lnvpair -lsec -luutil -lzfs -lc
CPPFLAGS += $(INCS) -D_REENTRANT
diff --git a/usr/src/lib/smbsrv/libmlsvc/common/libmlsvc.h b/usr/src/lib/smbsrv/libmlsvc/common/libmlsvc.h
index 99f10fc368..a2daead00d 100644
--- a/usr/src/lib/smbsrv/libmlsvc/common/libmlsvc.h
+++ b/usr/src/lib/smbsrv/libmlsvc/common/libmlsvc.h
@@ -49,8 +49,8 @@
extern "C" {
#endif
-extern uint32_t mlsvc_lookup_name(char *, smb_sid_t **, uint16_t *);
-extern uint32_t mlsvc_lookup_sid(smb_sid_t *, char **);
+uint32_t lsa_lookup_name(char *, uint16_t, smb_account_t *);
+uint32_t lsa_lookup_sid(smb_sid_t *, smb_account_t *);
/*
* SMB domain API to discover a domain controller and obtain domain
@@ -73,13 +73,6 @@ extern DWORD mlsvc_join(smb_domainex_t *, char *, char *);
*/
#define MLSVC_DOMAIN_MAX 32
-/*
- * Status code returned from enumeration RPCs to indicate
- * that the server has no more data. Normally returned at
- * severity level ERROR_SEVERITY_WARNING.
- */
-#define MLSVC_NO_MORE_DATA 0x1A
-
#define MLSVC_ANON_USER "IPC$"
char *mlsvc_ipc_name(int ipc_type, char *username);
@@ -110,7 +103,7 @@ typedef struct smb_autohome {
char *ah_container; /* ADS container distinguished name */
} smb_autohome_t;
-extern void smb_autohome_add(const char *);
+extern void smb_autohome_add(const smb_token_t *);
extern void smb_autohome_remove(const char *);
/*
@@ -151,7 +144,6 @@ int srvsvc_net_server_getinfo(char *, char *, srvsvc_server_info_t *);
typedef struct mlsvc_handle {
ndr_hdid_t handle;
ndr_client_t *clnt;
- uint32_t remote_os;
srvsvc_server_info_t svinfo;
} mlsvc_handle_t;
@@ -160,6 +152,8 @@ void ndr_rpc_fini(void);
int ndr_rpc_bind(mlsvc_handle_t *, char *, char *, char *, const char *);
void ndr_rpc_unbind(mlsvc_handle_t *);
int ndr_rpc_call(mlsvc_handle_t *, int, void *);
+void ndr_rpc_set_nonull(mlsvc_handle_t *);
+const srvsvc_server_info_t *ndr_rpc_server_info(mlsvc_handle_t *);
uint32_t ndr_rpc_server_os(mlsvc_handle_t *);
int ndr_rpc_get_ssnkey(mlsvc_handle_t *, unsigned char *, size_t);
void *ndr_rpc_malloc(mlsvc_handle_t *, size_t);
diff --git a/usr/src/lib/smbsrv/libmlsvc/common/lsalib.c b/usr/src/lib/smbsrv/libmlsvc/common/lsalib.c
index c091d63f9b..5545ab1d3a 100644
--- a/usr/src/lib/smbsrv/libmlsvc/common/lsalib.c
+++ b/usr/src/lib/smbsrv/libmlsvc/common/lsalib.c
@@ -239,9 +239,9 @@ lsa_enum_trusted_domains(char *server, char *domain,
enum_context = 0;
status = lsar_enum_trusted_domains(&domain_handle, &enum_context, info);
- if (status == MLSVC_NO_MORE_DATA) {
+ if (status == NT_STATUS_NO_MORE_DATA) {
/*
- * MLSVC_NO_MORE_DATA indicates that we
+ * NT_STATUS_NO_MORE_DATA indicates that we
* have all of the available information.
*/
status = NT_STATUS_SUCCESS;
@@ -279,9 +279,9 @@ lsa_enum_trusted_domains_ex(char *server, char *domain,
status = lsar_enum_trusted_domains_ex(&domain_handle, &enum_context,
info);
- if (status == MLSVC_NO_MORE_DATA) {
+ if (status == NT_STATUS_NO_MORE_DATA) {
/*
- * MLSVC_NO_MORE_DATA indicates that we
+ * NT_STATUS_NO_MORE_DATA indicates that we
* have all of the available information.
*/
status = NT_STATUS_SUCCESS;
@@ -357,14 +357,7 @@ lsa_lookup_name_domain(char *account_name, smb_account_t *info)
&domain_handle) != 0)
return (NT_STATUS_INVALID_PARAMETER);
- status = lsar_lookup_names2(&domain_handle, account_name, info);
- if (status == NT_STATUS_REVISION_MISMATCH) {
- /*
- * Not a Windows 2000 domain controller:
- * use the NT compatible call.
- */
- status = lsar_lookup_names(&domain_handle, account_name, info);
- }
+ status = lsar_lookup_names(&domain_handle, account_name, info);
(void) lsar_close(&domain_handle);
return (status);
@@ -547,17 +540,7 @@ lsa_lookup_sid_domain(smb_sid_t *sid, smb_account_t *ainfo)
&domain_handle) != 0)
return (NT_STATUS_INVALID_PARAMETER);
- status = lsar_lookup_sids2(&domain_handle, (struct mslsa_sid *)sid,
- ainfo);
-
- if (status == NT_STATUS_REVISION_MISMATCH) {
- /*
- * Not a Windows 2000 domain controller:
- * use the NT compatible call.
- */
- status = lsar_lookup_sids(&domain_handle,
- (struct mslsa_sid *)sid, ainfo);
- }
+ status = lsar_lookup_sids(&domain_handle, sid, ainfo);
(void) lsar_close(&domain_handle);
return (status);
diff --git a/usr/src/lib/smbsrv/libmlsvc/common/lsalib.h b/usr/src/lib/smbsrv/libmlsvc/common/lsalib.h
index afbf685bc5..f6f3f11fcd 100644
--- a/usr/src/lib/smbsrv/libmlsvc/common/lsalib.h
+++ b/usr/src/lib/smbsrv/libmlsvc/common/lsalib.h
@@ -45,6 +45,8 @@
extern "C" {
#endif
+typedef struct mslsa_sid lsa_sid_t;
+
/*
* lsalib.c
*/
@@ -70,11 +72,7 @@ int lsar_close(mlsvc_handle_t *);
int lsar_query_security_desc(mlsvc_handle_t *);
DWORD lsar_query_info_policy(mlsvc_handle_t *, WORD, smb_domain_t *);
uint32_t lsar_lookup_names(mlsvc_handle_t *, char *, smb_account_t *);
-uint32_t lsar_lookup_names2(mlsvc_handle_t *, char *, smb_account_t *);
-uint32_t lsar_lookup_sids(mlsvc_handle_t *, struct mslsa_sid *,
- smb_account_t *);
-uint32_t lsar_lookup_sids2(mlsvc_handle_t *, struct mslsa_sid *,
- smb_account_t *);
+uint32_t lsar_lookup_sids(mlsvc_handle_t *, smb_sid_t *, smb_account_t *);
int lsar_enum_accounts(mlsvc_handle_t *, DWORD *,
struct mslsa_EnumAccountBuf *);
diff --git a/usr/src/lib/smbsrv/libmlsvc/common/lsar_lookup.c b/usr/src/lib/smbsrv/libmlsvc/common/lsar_clnt.c
index 1121d67d6f..e01ac58363 100644
--- a/usr/src/lib/smbsrv/libmlsvc/common/lsar_lookup.c
+++ b/usr/src/lib/smbsrv/libmlsvc/common/lsar_clnt.c
@@ -24,22 +24,21 @@
*/
/*
- * Local Security Authority RPC (LSARPC) library interface functions for
- * query, lookup and enumeration calls.
+ * Local Security Authority RPC (LSAR) client-side interface.
*/
-
+#include <sys/errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
-#include <sys/errno.h>
#include <smbsrv/libsmb.h>
+#include <smbsrv/libmlsvc.h>
+#include <smbsrv/smbinfo.h>
#include <smbsrv/ntaccess.h>
#include <smbsrv/ntstatus.h>
#include <smbsrv/ntlocale.h>
#include <smbsrv/string.h>
-#include <smbsrv/libmlsvc.h>
#include <lsalib.h>
/*
@@ -49,13 +48,30 @@
#define MLSVC_MAX_RESPONSE_LEN 1024
/*
- * This structure is used when lookuping up names. We only lookup one
+ * This structure is used when looking up names. We only lookup one
* name at a time but the structure will allow for more.
*/
-typedef struct lookup_name_table {
- DWORD n_entry;
- mslsa_string_t name[8];
-} lookup_name_table_t;
+typedef struct lsa_names {
+ uint32_t n_entry;
+ mslsa_string_t name[8];
+} lsa_names_t;
+
+typedef DWORD (*lsar_nameop_t)(mlsvc_handle_t *, lsa_names_t *,
+ smb_account_t *);
+
+static uint32_t lsar_lookup_names1(mlsvc_handle_t *, lsa_names_t *,
+ smb_account_t *);
+static uint32_t lsar_lookup_names2(mlsvc_handle_t *, lsa_names_t *,
+ smb_account_t *);
+static uint32_t lsar_lookup_names3(mlsvc_handle_t *, lsa_names_t *,
+ smb_account_t *);
+static uint32_t lsar_lookup_sids1(mlsvc_handle_t *, lsa_sid_t *,
+ smb_account_t *);
+static uint32_t lsar_lookup_sids2(mlsvc_handle_t *, lsa_sid_t *,
+ smb_account_t *account);
+
+static char *lsar_get_username(const char *);
+static void smb_account_trace(const smb_account_t *);
static void lsar_set_trusted_domains_ex(struct mslsa_EnumTrustedDomainBufEx *,
smb_trusted_domains_t *);
@@ -63,6 +79,190 @@ static void lsar_set_trusted_domains(struct mslsa_EnumTrustedDomainBuf *,
smb_trusted_domains_t *);
/*
+ * lsar_open
+ *
+ * This is a wrapper round lsar_open_policy2 to ensure that we connect
+ * using the appropriate domain information.
+ *
+ * If username argument is NULL, an anonymous connection will be established.
+ * Otherwise, an authenticated connection will be established.
+ *
+ * On success 0 is returned. Otherwise a -ve error code.
+ */
+int lsar_open(char *server, char *domain, char *username,
+ mlsvc_handle_t *domain_handle)
+{
+ if (server == NULL || domain == NULL)
+ return (-1);
+
+ if (username == NULL)
+ username = MLSVC_ANON_USER;
+
+ return (lsar_open_policy2(server, domain, username, domain_handle));
+}
+
+/*
+ * lsar_open_policy2
+ *
+ * Obtain an LSA policy handle. A policy handle is required to access
+ * LSA resources on a remote server. The server name supplied here does
+ * not need the double backslash prefix; it is added here. Call this
+ * function via lsar_open to ensure that the appropriate connection is
+ * in place.
+ *
+ * I'm not sure if it makes a difference whether we use GENERIC_EXECUTE
+ * or STANDARD_RIGHTS_EXECUTE. For a long time I used the standard bit
+ * and then I added the generic bit while working on privileges because
+ * NT sets that bit. I don't think it matters.
+ *
+ * Returns 0 on success. Otherwise non-zero to indicate a failure.
+ */
+int
+lsar_open_policy2(char *server, char *domain, char *username,
+ mlsvc_handle_t *lsa_handle)
+{
+ struct mslsa_OpenPolicy2 arg;
+ int opnum;
+ int len;
+ int rc;
+
+ rc = ndr_rpc_bind(lsa_handle, server, domain, username, "LSARPC");
+ if (rc != 0)
+ return (-1);
+
+ opnum = LSARPC_OPNUM_OpenPolicy2;
+ bzero(&arg, sizeof (struct mslsa_OpenPolicy2));
+
+ len = strlen(server) + 4;
+ arg.servername = ndr_rpc_malloc(lsa_handle, len);
+ if (arg.servername == NULL) {
+ ndr_rpc_unbind(lsa_handle);
+ return (-1);
+ }
+
+ (void) snprintf((char *)arg.servername, len, "\\\\%s", server);
+ arg.attributes.length = sizeof (struct mslsa_object_attributes);
+
+ if (ndr_rpc_server_os(lsa_handle) == NATIVE_OS_WIN2000) {
+ arg.desiredAccess = MAXIMUM_ALLOWED;
+ } else {
+ arg.desiredAccess = GENERIC_EXECUTE
+ | STANDARD_RIGHTS_EXECUTE
+ | POLICY_VIEW_LOCAL_INFORMATION
+ | POLICY_LOOKUP_NAMES;
+ }
+
+ if ((rc = ndr_rpc_call(lsa_handle, opnum, &arg)) != 0) {
+ ndr_rpc_unbind(lsa_handle);
+ return (-1);
+ }
+
+ if (arg.status != 0) {
+ rc = -1;
+ } else {
+ (void) memcpy(&lsa_handle->handle, &arg.domain_handle,
+ sizeof (ndr_hdid_t));
+
+ if (ndr_is_null_handle(lsa_handle))
+ rc = -1;
+ }
+
+ ndr_rpc_release(lsa_handle);
+
+ if (rc != 0)
+ ndr_rpc_unbind(lsa_handle);
+ return (rc);
+}
+
+/*
+ * lsar_open_account
+ *
+ * Obtain an LSA account handle. The lsa_handle must be a valid handle
+ * obtained via lsar_open_policy2. The main thing to remember here is
+ * to set up the context in the lsa_account_handle. I'm not sure what
+ * the requirements are for desired access. Some values require admin
+ * access.
+ *
+ * Returns 0 on success. Otherwise non-zero to indicate a failure.
+ */
+int
+lsar_open_account(mlsvc_handle_t *lsa_handle, struct mslsa_sid *sid,
+ mlsvc_handle_t *lsa_account_handle)
+{
+ struct mslsa_OpenAccount arg;
+ int opnum;
+ int rc;
+
+ if (ndr_is_null_handle(lsa_handle) || sid == NULL)
+ return (-1);
+
+ opnum = LSARPC_OPNUM_OpenAccount;
+ bzero(&arg, sizeof (struct mslsa_OpenAccount));
+
+ (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t));
+ arg.sid = sid;
+ arg.access_mask = STANDARD_RIGHTS_REQUIRED
+#if 0
+ | POLICY_VIEW_AUDIT_INFORMATION
+ | POLICY_GET_PRIVATE_INFORMATION
+ | POLICY_TRUST_ADMIN
+#endif
+ | POLICY_VIEW_LOCAL_INFORMATION;
+
+ if ((rc = ndr_rpc_call(lsa_handle, opnum, &arg)) != 0)
+ return (-1);
+
+ if (arg.status != 0) {
+ rc = -1;
+ } else {
+ ndr_inherit_handle(lsa_account_handle, lsa_handle);
+
+ (void) memcpy(&lsa_account_handle->handle,
+ &arg.account_handle, sizeof (ndr_hdid_t));
+
+ if (ndr_is_null_handle(lsa_account_handle))
+ rc = -1;
+ }
+
+ ndr_rpc_release(lsa_handle);
+ return (rc);
+}
+
+/*
+ * lsar_close
+ *
+ * Close the LSA connection associated with the handle. The lsa_handle
+ * must be a valid handle obtained via a call to lsar_open_policy2 or
+ * lsar_open_account. On success the handle will be zeroed out to
+ * ensure that it is not used again. If this is the top level handle
+ * (i.e. the one obtained via lsar_open_policy2) the pipe is closed.
+ *
+ * Returns 0 on success. Otherwise non-zero to indicate a failure.
+ */
+int
+lsar_close(mlsvc_handle_t *lsa_handle)
+{
+ struct mslsa_CloseHandle arg;
+ int opnum;
+
+ if (ndr_is_null_handle(lsa_handle))
+ return (-1);
+
+ opnum = LSARPC_OPNUM_CloseHandle;
+ bzero(&arg, sizeof (struct mslsa_CloseHandle));
+ (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t));
+
+ (void) ndr_rpc_call(lsa_handle, opnum, &arg);
+ ndr_rpc_release(lsa_handle);
+
+ if (ndr_is_bind_handle(lsa_handle))
+ ndr_rpc_unbind(lsa_handle);
+
+ bzero(lsa_handle, sizeof (mlsvc_handle_t));
+ return (0);
+}
+
+/*
* lsar_query_security_desc
*
* Don't use this call yet. It is just a place holder for now.
@@ -70,9 +270,9 @@ static void lsar_set_trusted_domains(struct mslsa_EnumTrustedDomainBuf *,
int
lsar_query_security_desc(mlsvc_handle_t *lsa_handle)
{
- struct mslsa_QuerySecurityObject arg;
- int rc;
- int opnum;
+ struct mslsa_QuerySecurityObject arg;
+ int rc;
+ int opnum;
opnum = LSARPC_OPNUM_QuerySecurityObject;
@@ -84,7 +284,6 @@ lsar_query_security_desc(mlsvc_handle_t *lsa_handle)
return (rc);
}
-
/*
* lsar_query_info_policy
*
@@ -105,14 +304,14 @@ DWORD
lsar_query_info_policy(mlsvc_handle_t *lsa_handle, WORD infoClass,
smb_domain_t *info)
{
- struct mslsa_QueryInfoPolicy arg;
- struct mslsa_PrimaryDomainInfo *pd_info;
- struct mslsa_AccountDomainInfo *ad_info;
- struct mslsa_DnsDomainInfo *dns_info;
- char guid_str[UUID_PRINTABLE_STRING_LENGTH];
- char sidstr[SMB_SID_STRSZ];
- int opnum;
- DWORD status;
+ struct mslsa_QueryInfoPolicy arg;
+ struct mslsa_PrimaryDomainInfo *pd_info;
+ struct mslsa_AccountDomainInfo *ad_info;
+ struct mslsa_DnsDomainInfo *dns_info;
+ char guid_str[UUID_PRINTABLE_STRING_LENGTH];
+ char sidstr[SMB_SID_STRSZ];
+ int opnum;
+ DWORD status;
if (lsa_handle == NULL || info == NULL)
return (NT_STATUS_INVALID_PARAMETER);
@@ -181,53 +380,34 @@ lsar_query_info_policy(mlsvc_handle_t *lsa_handle, WORD infoClass,
}
/*
- * lsar_lookup_names
- *
- * Lookup a name and obtain the domain and user rid. The RPC call will
- * actually support lookup of multiple names but we probably don't
- * need to do that. On the final system the lookup level should be
- * level 2 but for now we want to restrict it to level 1 so that we
- * don't crash the PDC when we get things wrong.
- *
- * If the lookup fails, the status will typically be
- * NT_STATUS_NONE_MAPPED.
+ * Lookup a name and obtain the sid/rid.
+ * This is a wrapper for the various lookup sid RPCs.
*/
uint32_t
lsar_lookup_names(mlsvc_handle_t *lsa_handle, char *name, smb_account_t *info)
{
- struct mslsa_LookupNames arg;
- struct mslsa_rid_entry *rid_entry;
- struct mslsa_domain_entry *domain_entry;
- lookup_name_table_t name_table;
- uint32_t status = NT_STATUS_SUCCESS;
- char *domname;
- int opnum;
- size_t length;
- char *p;
+ static lsar_nameop_t ops[] = {
+ lsar_lookup_names3,
+ lsar_lookup_names2,
+ lsar_lookup_names1
+ };
+
+ const srvsvc_server_info_t *svinfo;
+ lsa_names_t names;
+ char *p;
+ uint32_t length;
+ uint32_t status = NT_STATUS_INVALID_PARAMETER;
+ int n_op = (sizeof (ops) / sizeof (ops[0]));
+ int i;
if (lsa_handle == NULL || name == NULL || info == NULL)
return (NT_STATUS_INVALID_PARAMETER);
bzero(info, sizeof (smb_account_t));
- opnum = LSARPC_OPNUM_LookupNames;
-
- bzero(&arg, sizeof (struct mslsa_LookupNames));
- (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t));
-
- arg.name_table = (struct mslsa_lup_name_table *)&name_table;
- name_table.n_entry = 1;
-
- /*
- * Windows NT expects the name length to exclude the terminating
- * wchar null but doesn't care whether the allosize includes or
- * excludes the null char. Windows 2000 insists that both the
- * length and the allosize include the wchar null.
- *
- * Note: NT returns an error if the mapped_count is non-zero
- * when the RPC is called.
- */
- if (ndr_rpc_server_os(lsa_handle) == NATIVE_OS_WIN2000) {
+ svinfo = ndr_rpc_server_info(lsa_handle);
+ if (svinfo->sv_os == NATIVE_OS_WIN2000 &&
+ svinfo->sv_version_major == 5 && svinfo->sv_version_minor == 0) {
/*
* Windows 2000 doesn't like an LSA lookup for
* DOMAIN\Administrator.
@@ -239,16 +419,148 @@ lsar_lookup_names(mlsvc_handle_t *lsa_handle, char *name, smb_account_t *info)
name = p;
}
- length = smb_wcequiv_strlen(name) + sizeof (smb_wchar_t);
- arg.lookup_level = MSLSA_LOOKUP_LEVEL_1;
+ }
+
+ length = smb_wcequiv_strlen(name);
+ names.name[0].length = length;
+ names.name[0].allosize = length;
+ names.name[0].str = (unsigned char *)name;
+ names.n_entry = 1;
+
+ if (ndr_rpc_server_os(lsa_handle) == NATIVE_OS_WIN2000) {
+ for (i = 0; i < n_op; ++i) {
+ ndr_rpc_set_nonull(lsa_handle);
+ status = (*ops[i])(lsa_handle, &names, info);
+
+ if (status != NT_STATUS_INVALID_PARAMETER)
+ break;
+ }
} else {
- length = smb_wcequiv_strlen(name);
- arg.lookup_level = MSLSA_LOOKUP_LEVEL_1;
+ ndr_rpc_set_nonull(lsa_handle);
+ status = lsar_lookup_names1(lsa_handle, &names, info);
}
- name_table.name[0].length = length;
- name_table.name[0].allosize = length;
- name_table.name[0].str = (unsigned char *)name;
+ if (status == NT_STATUS_SUCCESS) {
+ info->a_name = lsar_get_username(name);
+
+ if (!smb_account_validate(info)) {
+ smb_account_free(info);
+ status = NT_STATUS_NO_MEMORY;
+ } else {
+ smb_account_trace(info);
+ }
+ }
+
+ return (status);
+}
+
+/*
+ * The name may be in one of the following forms:
+ *
+ * domain\username
+ * domain/username
+ * username
+ * username@domain
+ *
+ * Return a strdup'd copy of the username. The caller is responsible
+ * for freeing the allocated memory.
+ */
+static char *
+lsar_get_username(const char *name)
+{
+ char tmp[MAXNAMELEN];
+ char *dp = NULL;
+ char *np = NULL;
+
+ (void) strlcpy(tmp, name, MAXNAMELEN);
+ smb_name_parse(tmp, &np, &dp);
+
+ if (dp != NULL && np != NULL)
+ return (strdup(np));
+ else
+ return (strdup(name));
+}
+
+/*
+ * lsar_lookup_names1
+ *
+ * Lookup a name and obtain the domain and user rid.
+ *
+ * Note: NT returns an error if the mapped_count is non-zero when the RPC
+ * is called.
+ *
+ * If the lookup fails, the status will typically be NT_STATUS_NONE_MAPPED.
+ */
+static uint32_t
+lsar_lookup_names1(mlsvc_handle_t *lsa_handle, lsa_names_t *names,
+ smb_account_t *info)
+{
+ struct mslsa_LookupNames arg;
+ struct mslsa_rid_entry *rid_entry;
+ struct mslsa_domain_entry *domain_entry;
+ uint32_t status = NT_STATUS_SUCCESS;
+ char *domname;
+ int opnum = LSARPC_OPNUM_LookupNames;
+
+ bzero(&arg, sizeof (struct mslsa_LookupNames));
+ (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t));
+ arg.lookup_level = LSA_LOOKUP_WKSTA;
+ arg.name_table = (struct mslsa_lup_name_table *)names;
+
+ if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) {
+ ndr_rpc_release(lsa_handle);
+ return (NT_STATUS_INVALID_PARAMETER);
+ }
+
+ if (arg.status != NT_STATUS_SUCCESS) {
+ ndr_rpc_status(lsa_handle, opnum, arg.status);
+ ndr_rpc_release(lsa_handle);
+ return (NT_SC_VALUE(arg.status));
+ }
+
+ if (arg.mapped_count == 0) {
+ ndr_rpc_release(lsa_handle);
+ return (NT_STATUS_NONE_MAPPED);
+ }
+
+ rid_entry = &arg.translated_sids.rids[0];
+ if (rid_entry->domain_index != 0) {
+ ndr_rpc_release(lsa_handle);
+ return (NT_STATUS_NONE_MAPPED);
+ }
+
+ domain_entry = &arg.domain_table->entries[0];
+
+ info->a_type = rid_entry->sid_name_use;
+ info->a_domsid = smb_sid_dup((smb_sid_t *)domain_entry->domain_sid);
+ if ((domname = (char *)domain_entry->domain_name.str) != NULL)
+ info->a_domain = strdup(domname);
+ info->a_rid = rid_entry->rid;
+ info->a_sid = smb_sid_splice(info->a_domsid, info->a_rid);
+
+ ndr_rpc_release(lsa_handle);
+ return (status);
+}
+
+/*
+ * lsar_lookup_names2
+ */
+static uint32_t
+lsar_lookup_names2(mlsvc_handle_t *lsa_handle, lsa_names_t *names,
+ smb_account_t *info)
+{
+ struct lsar_LookupNames2 arg;
+ struct lsar_rid_entry2 *rid_entry;
+ struct mslsa_domain_entry *domain_entry;
+ uint32_t status = NT_STATUS_SUCCESS;
+ char *domname;
+ int opnum = LSARPC_OPNUM_LookupNames2;
+
+ bzero(&arg, sizeof (struct lsar_LookupNames2));
+ (void) memcpy(&arg.policy_handle, lsa_handle, sizeof (mslsa_handle_t));
+ arg.lookup_level = LSA_LOOKUP_WKSTA;
+ arg.client_revision = LSA_CLIENT_REVISION_AD;
+ arg.name_table = (struct mslsa_lup_name_table *)names;
if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) {
ndr_rpc_release(lsa_handle);
@@ -275,56 +587,256 @@ lsar_lookup_names(mlsvc_handle_t *lsa_handle, char *name, smb_account_t *info)
domain_entry = &arg.domain_table->entries[0];
info->a_type = rid_entry->sid_name_use;
- info->a_name = strdup(name);
info->a_domsid = smb_sid_dup((smb_sid_t *)domain_entry->domain_sid);
if ((domname = (char *)domain_entry->domain_name.str) != NULL)
info->a_domain = strdup(domname);
info->a_rid = rid_entry->rid;
info->a_sid = smb_sid_splice(info->a_domsid, info->a_rid);
- if (!smb_account_validate(info)) {
- smb_account_free(info);
- status = NT_STATUS_NO_MEMORY;
+ ndr_rpc_release(lsa_handle);
+ return (status);
+}
+
+/*
+ * lsar_lookup_names3
+ */
+static uint32_t
+lsar_lookup_names3(mlsvc_handle_t *lsa_handle, lsa_names_t *names,
+ smb_account_t *info)
+{
+ struct lsar_LookupNames3 arg;
+ lsar_translated_sid_ex2_t *sid_entry;
+ struct mslsa_domain_entry *domain_entry;
+ uint32_t status = NT_STATUS_SUCCESS;
+ char *domname;
+ int opnum = LSARPC_OPNUM_LookupNames3;
+
+ bzero(&arg, sizeof (struct lsar_LookupNames3));
+ (void) memcpy(&arg.policy_handle, lsa_handle, sizeof (mslsa_handle_t));
+ arg.lookup_level = LSA_LOOKUP_WKSTA;
+ arg.client_revision = LSA_CLIENT_REVISION_AD;
+ arg.name_table = (struct mslsa_lup_name_table *)names;
+
+ if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) {
+ ndr_rpc_release(lsa_handle);
+ return (NT_STATUS_INVALID_PARAMETER);
+ }
+
+ if (arg.status != NT_STATUS_SUCCESS) {
+ ndr_rpc_status(lsa_handle, opnum, arg.status);
+ ndr_rpc_release(lsa_handle);
+ return (NT_SC_VALUE(arg.status));
}
+ if (arg.mapped_count == 0) {
+ ndr_rpc_release(lsa_handle);
+ return (NT_STATUS_NONE_MAPPED);
+ }
+
+ sid_entry = &arg.translated_sids.sids[0];
+ if (sid_entry->domain_index != 0) {
+ ndr_rpc_release(lsa_handle);
+ return (NT_STATUS_NONE_MAPPED);
+ }
+
+ domain_entry = &arg.domain_table->entries[0];
+
+ info->a_type = sid_entry->sid_name_use;
+ info->a_domsid = smb_sid_dup((smb_sid_t *)domain_entry->domain_sid);
+ if ((domname = (char *)domain_entry->domain_name.str) != NULL)
+ info->a_domain = strdup(domname);
+ info->a_sid = smb_sid_dup((smb_sid_t *)sid_entry->sid);
+ (void) smb_sid_getrid(info->a_sid, &info->a_rid);
+
ndr_rpc_release(lsa_handle);
return (status);
}
/*
- * lsar_lookup_sids
+ * lsar_lookup_names4
+ *
+ * This function is only valid if the remote RPC server is a domain
+ * controller and requires the security extensions defined in MS-RPCE.
*
- * Lookup a sid and obtain the domain sid and user name. The RPC call
- * will actually support lookup of multiple sids but we probably don't
- * need to do that. On the final system the lookup level should be
- * level 2 but for now we want to restrict it to level 1 so that we
- * don't crash the PDC when we get things wrong.
+ * Domain controllers will return RPC_NT_PROTSEQ_NOT_SUPPORTED here
+ * because we don't support the RPC_C_AUTHN_NETLOGON security provider.
+ * Non-domain controllers will return NT_STATUS_INVALID_SERVER_STATE.
+ */
+static uint32_t /*LINTED E_STATIC_UNUSED*/
+lsar_lookup_names4(mlsvc_handle_t *lsa_handle, lsa_names_t *names,
+ smb_account_t *info)
+{
+ struct lsar_LookupNames4 arg;
+ lsar_translated_sid_ex2_t *sid_entry;
+ struct mslsa_domain_entry *domain_entry;
+ uint32_t status = NT_STATUS_SUCCESS;
+ char *domname;
+ int opnum = LSARPC_OPNUM_LookupNames4;
+
+ bzero(&arg, sizeof (struct lsar_LookupNames4));
+ arg.lookup_level = LSA_LOOKUP_WKSTA;
+ arg.client_revision = LSA_CLIENT_REVISION_AD;
+ arg.name_table = (struct mslsa_lup_name_table *)names;
+
+ if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) {
+ ndr_rpc_release(lsa_handle);
+ return (NT_STATUS_INVALID_PARAMETER);
+ }
+
+ if (arg.status != NT_STATUS_SUCCESS) {
+ ndr_rpc_status(lsa_handle, opnum, arg.status);
+ ndr_rpc_release(lsa_handle);
+ if (arg.status == RPC_NT_PROTSEQ_NOT_SUPPORTED ||
+ arg.status == NT_STATUS_INVALID_SERVER_STATE)
+ return (NT_STATUS_INVALID_PARAMETER);
+ return (NT_SC_VALUE(arg.status));
+ }
+
+ if (arg.mapped_count == 0) {
+ ndr_rpc_release(lsa_handle);
+ return (NT_STATUS_NONE_MAPPED);
+ }
+
+ sid_entry = &arg.translated_sids.sids[0];
+ if (sid_entry->domain_index != 0) {
+ ndr_rpc_release(lsa_handle);
+ return (NT_STATUS_NONE_MAPPED);
+ }
+
+ domain_entry = &arg.domain_table->entries[0];
+
+ info->a_type = sid_entry->sid_name_use;
+ info->a_domsid = smb_sid_dup((smb_sid_t *)domain_entry->domain_sid);
+ if ((domname = (char *)domain_entry->domain_name.str) != NULL)
+ info->a_domain = strdup(domname);
+ info->a_sid = smb_sid_dup((smb_sid_t *)sid_entry->sid);
+ (void) smb_sid_getrid(info->a_sid, &info->a_rid);
+
+ ndr_rpc_release(lsa_handle);
+ return (status);
+}
+
+/*
+ * Lookup a sid and obtain the domain sid and account name.
+ * This is a wrapper for the various lookup sid RPCs.
*/
uint32_t
-lsar_lookup_sids(mlsvc_handle_t *lsa_handle, struct mslsa_sid *sid,
+lsar_lookup_sids(mlsvc_handle_t *lsa_handle, smb_sid_t *sid,
smb_account_t *account)
{
- struct mslsa_LookupSids arg;
- struct mslsa_lup_sid_entry sid_entry;
- struct mslsa_name_entry *name_entry;
- struct mslsa_domain_entry *domain_entry;
- uint32_t status = NT_STATUS_SUCCESS;
- char *name;
- int opnum;
+ char sidbuf[SMB_SID_STRSZ];
+ uint32_t status;
if (lsa_handle == NULL || sid == NULL || account == NULL)
return (NT_STATUS_INVALID_PARAMETER);
bzero(account, sizeof (smb_account_t));
- opnum = LSARPC_OPNUM_LookupSids;
+ bzero(sidbuf, SMB_SID_STRSZ);
+ smb_sid_tostr(sid, sidbuf);
+ smb_tracef("%s", sidbuf);
+
+ if (ndr_rpc_server_os(lsa_handle) == NATIVE_OS_WIN2000)
+ status = lsar_lookup_sids2(lsa_handle, (lsa_sid_t *)sid,
+ account);
+ else
+ status = lsar_lookup_sids1(lsa_handle, (lsa_sid_t *)sid,
+ account);
+
+ if (status == NT_STATUS_SUCCESS) {
+ if (!smb_account_validate(account)) {
+ smb_account_free(account);
+ status = NT_STATUS_NO_MEMORY;
+ } else {
+ smb_account_trace(account);
+ }
+ }
+
+ return (status);
+}
+
+/*
+ * lsar_lookup_sids1
+ */
+static uint32_t
+lsar_lookup_sids1(mlsvc_handle_t *lsa_handle, lsa_sid_t *sid,
+ smb_account_t *account)
+{
+ struct mslsa_LookupSids arg;
+ struct mslsa_lup_sid_entry sid_entry;
+ struct mslsa_name_entry *name_entry;
+ struct mslsa_domain_entry *domain_entry;
+ uint32_t status = NT_STATUS_SUCCESS;
+ char *name;
+ int opnum = LSARPC_OPNUM_LookupSids;
bzero(&arg, sizeof (struct mslsa_LookupSids));
(void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t));
- arg.lookup_level = MSLSA_LOOKUP_LEVEL_2;
+ arg.lookup_level = LSA_LOOKUP_WKSTA;
+
+ sid_entry.psid = sid;
+ arg.lup_sid_table.n_entry = 1;
+ arg.lup_sid_table.entries = &sid_entry;
+
+ if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) {
+ ndr_rpc_release(lsa_handle);
+ return (NT_STATUS_INVALID_PARAMETER);
+ }
+
+ if (arg.status != NT_STATUS_SUCCESS) {
+ ndr_rpc_status(lsa_handle, opnum, arg.status);
+ ndr_rpc_release(lsa_handle);
+ return (NT_SC_VALUE(arg.status));
+ }
+
+ if (arg.mapped_count == 0) {
+ ndr_rpc_release(lsa_handle);
+ return (NT_STATUS_NONE_MAPPED);
+ }
+
+ name_entry = &arg.name_table.entries[0];
+ if (name_entry->domain_ix != 0) {
+ ndr_rpc_release(lsa_handle);
+ return (NT_STATUS_NONE_MAPPED);
+ }
+
+ name = (char *)name_entry->name.str;
+ account->a_name = (name) ? strdup(name) : strdup("");
+ account->a_type = name_entry->sid_name_use;
+ account->a_sid = smb_sid_dup((smb_sid_t *)sid);
+ (void) smb_sid_getrid(account->a_sid, &account->a_rid);
+
+ domain_entry = &arg.domain_table->entries[0];
+ if ((name = (char *)domain_entry->domain_name.str) != NULL)
+ account->a_domain = strdup(name);
+ account->a_domsid = smb_sid_dup((smb_sid_t *)domain_entry->domain_sid);
+
+ ndr_rpc_release(lsa_handle);
+ return (status);
+}
+
+/*
+ * lsar_lookup_sids2
+ */
+static uint32_t
+lsar_lookup_sids2(mlsvc_handle_t *lsa_handle, lsa_sid_t *sid,
+ smb_account_t *account)
+{
+ struct lsar_lookup_sids2 arg;
+ struct lsar_name_entry2 *name_entry;
+ struct mslsa_lup_sid_entry sid_entry;
+ struct mslsa_domain_entry *domain_entry;
+ uint32_t status = NT_STATUS_SUCCESS;
+ char *name;
+ int opnum = LSARPC_OPNUM_LookupSids2;
+
+ bzero(&arg, sizeof (struct lsar_lookup_sids2));
+ (void) memcpy(&arg.policy_handle, lsa_handle, sizeof (mslsa_handle_t));
sid_entry.psid = sid;
arg.lup_sid_table.n_entry = 1;
arg.lup_sid_table.entries = &sid_entry;
+ arg.lookup_level = LSA_LOOKUP_WKSTA;
+ arg.client_revision = LSA_CLIENT_REVISION_AD;
if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) {
ndr_rpc_release(lsa_handle);
@@ -352,17 +864,83 @@ lsar_lookup_sids(mlsvc_handle_t *lsa_handle, struct mslsa_sid *sid,
account->a_name = (name) ? strdup(name) : strdup("");
account->a_type = name_entry->sid_name_use;
account->a_sid = smb_sid_dup((smb_sid_t *)sid);
+ (void) smb_sid_getrid(account->a_sid, &account->a_rid);
domain_entry = &arg.domain_table->entries[0];
if ((name = (char *)domain_entry->domain_name.str) != NULL)
account->a_domain = strdup(name);
account->a_domsid = smb_sid_dup((smb_sid_t *)domain_entry->domain_sid);
- if (!smb_account_validate(account)) {
- smb_account_free(account);
- status = NT_STATUS_NO_MEMORY;
+ ndr_rpc_release(lsa_handle);
+ return (status);
+}
+
+/*
+ * lsar_lookup_sids3
+ *
+ * This function is only valid if the remote RPC server is a domain
+ * controller and requires the security extensions defined in MS-RPCE.
+ *
+ * Domain controllers will return RPC_NT_PROTSEQ_NOT_SUPPORTED here
+ * because we don't support the RPC_C_AUTHN_NETLOGON security provider.
+ * Non-domain controllers will return NT_STATUS_INVALID_SERVER_STATE.
+ */
+static uint32_t /*LINTED E_STATIC_UNUSED*/
+lsar_lookup_sids3(mlsvc_handle_t *lsa_handle, lsa_sid_t *sid,
+ smb_account_t *account)
+{
+ struct lsar_lookup_sids3 arg;
+ lsar_translated_name_ex_t *name_entry;
+ struct mslsa_lup_sid_entry sid_entry;
+ struct mslsa_domain_entry *domain_entry;
+ uint32_t status = NT_STATUS_SUCCESS;
+ char *name;
+ int opnum = LSARPC_OPNUM_LookupSids3;
+
+ bzero(&arg, sizeof (struct lsar_lookup_sids3));
+
+ sid_entry.psid = sid;
+ arg.lup_sid_table.n_entry = 1;
+ arg.lup_sid_table.entries = &sid_entry;
+ arg.lookup_level = LSA_LOOKUP_WKSTA;
+ arg.client_revision = LSA_CLIENT_REVISION_AD;
+
+ if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) {
+ ndr_rpc_release(lsa_handle);
+ return (NT_STATUS_INVALID_PARAMETER);
+ }
+
+ if (arg.status != NT_STATUS_SUCCESS) {
+ ndr_rpc_status(lsa_handle, opnum, arg.status);
+ ndr_rpc_release(lsa_handle);
+ if (arg.status == RPC_NT_PROTSEQ_NOT_SUPPORTED ||
+ arg.status == NT_STATUS_INVALID_SERVER_STATE)
+ return (NT_STATUS_INVALID_PARAMETER);
+ return (NT_SC_VALUE(arg.status));
+ }
+
+ if (arg.mapped_count == 0) {
+ ndr_rpc_release(lsa_handle);
+ return (NT_STATUS_NONE_MAPPED);
+ }
+
+ name_entry = &arg.name_table.entries[0];
+ if (name_entry->domain_ix != 0) {
+ ndr_rpc_release(lsa_handle);
+ return (NT_STATUS_NONE_MAPPED);
}
+ name = (char *)name_entry->name.str;
+ account->a_name = (name) ? strdup(name) : strdup("");
+ account->a_type = name_entry->sid_name_use;
+ account->a_sid = smb_sid_dup((smb_sid_t *)sid);
+ (void) smb_sid_getrid(account->a_sid, &account->a_rid);
+
+ domain_entry = &arg.domain_table->entries[0];
+ if ((name = (char *)domain_entry->domain_name.str) != NULL)
+ account->a_domain = strdup(name);
+ account->a_domsid = smb_sid_dup((smb_sid_t *)domain_entry->domain_sid);
+
ndr_rpc_release(lsa_handle);
return (status);
}
@@ -384,13 +962,13 @@ int
lsar_enum_accounts(mlsvc_handle_t *lsa_handle, DWORD *enum_context,
struct mslsa_EnumAccountBuf *accounts)
{
- struct mslsa_EnumerateAccounts arg;
- struct mslsa_AccountInfo *info;
- int opnum;
- int rc;
- DWORD n_entries;
- DWORD i;
- int nbytes;
+ struct mslsa_EnumerateAccounts arg;
+ struct mslsa_AccountInfo *info;
+ int opnum;
+ int rc;
+ DWORD n_entries;
+ DWORD i;
+ int nbytes;
if (lsa_handle == NULL || enum_context == NULL || accounts == NULL)
return (-1);
@@ -408,7 +986,8 @@ lsar_enum_accounts(mlsvc_handle_t *lsa_handle, DWORD *enum_context,
rc = ndr_rpc_call(lsa_handle, opnum, &arg);
if (rc == 0) {
if (arg.status != 0) {
- if ((arg.status & 0x00FFFFFF) == MLSVC_NO_MORE_DATA) {
+ if ((arg.status & 0x00FFFFFF) ==
+ NT_STATUS_NO_MORE_DATA) {
*enum_context = arg.enum_context;
} else {
ndr_rpc_status(lsa_handle, opnum, arg.status);
@@ -424,7 +1003,7 @@ lsar_enum_accounts(mlsvc_handle_t *lsa_handle, DWORD *enum_context,
}
for (i = 0; i < n_entries; ++i)
- info[i].sid = (struct mslsa_sid *)smb_sid_dup(
+ info[i].sid = (lsa_sid_t *)smb_sid_dup(
(smb_sid_t *)arg.enum_buf->info[i].sid);
accounts->entries_read = n_entries;
@@ -456,9 +1035,9 @@ DWORD
lsar_enum_trusted_domains(mlsvc_handle_t *lsa_handle, DWORD *enum_context,
smb_trusted_domains_t *list)
{
- struct mslsa_EnumTrustedDomain arg;
- int opnum;
- DWORD status;
+ struct mslsa_EnumTrustedDomain arg;
+ int opnum;
+ DWORD status;
if (list == NULL)
return (NT_STATUS_INVALID_PARAMETER);
@@ -481,7 +1060,7 @@ lsar_enum_trusted_domains(mlsvc_handle_t *lsa_handle, DWORD *enum_context,
* status 0x8000001A means NO_MORE_DATA,
* which is not an error.
*/
- if (status != MLSVC_NO_MORE_DATA)
+ if (status != NT_STATUS_NO_MORE_DATA)
ndr_rpc_status(lsa_handle, opnum, arg.status);
} else if (arg.enum_buf->entries_read == 0) {
*enum_context = arg.enum_context;
@@ -500,9 +1079,9 @@ DWORD
lsar_enum_trusted_domains_ex(mlsvc_handle_t *lsa_handle, DWORD *enum_context,
smb_trusted_domains_t *list)
{
- struct mslsa_EnumTrustedDomainEx arg;
- int opnum;
- DWORD status;
+ struct mslsa_EnumTrustedDomainEx arg;
+ int opnum;
+ DWORD status;
if (list == NULL)
return (NT_STATUS_INVALID_PARAMETER);
@@ -525,7 +1104,7 @@ lsar_enum_trusted_domains_ex(mlsvc_handle_t *lsa_handle, DWORD *enum_context,
* status 0x8000001A means NO_MORE_DATA,
* which is not an error.
*/
- if (status != MLSVC_NO_MORE_DATA)
+ if (status != NT_STATUS_NO_MORE_DATA)
ndr_rpc_status(lsa_handle, opnum, arg.status);
} else if (arg.enum_buf->entries_read == 0) {
*enum_context = arg.enum_context;
@@ -549,9 +1128,9 @@ lsar_enum_trusted_domains_ex(mlsvc_handle_t *lsa_handle, DWORD *enum_context,
int
lsar_enum_privs_account(mlsvc_handle_t *account_handle, smb_account_t *account)
{
- struct mslsa_EnumPrivsAccount arg;
- int opnum;
- int rc;
+ struct mslsa_EnumPrivsAccount arg;
+ int opnum;
+ int rc;
opnum = LSARPC_OPNUM_EnumPrivsAccount;
@@ -581,10 +1160,10 @@ int
lsar_lookup_priv_value(mlsvc_handle_t *lsa_handle, char *name,
struct ms_luid *luid)
{
- struct mslsa_LookupPrivValue arg;
- int opnum;
- int rc;
- size_t length;
+ struct mslsa_LookupPrivValue arg;
+ int opnum;
+ int rc;
+ size_t length;
if (lsa_handle == NULL || name == NULL || luid == NULL)
return (-1);
@@ -626,9 +1205,9 @@ int
lsar_lookup_priv_name(mlsvc_handle_t *lsa_handle, struct ms_luid *luid,
char *name, int namelen)
{
- struct mslsa_LookupPrivName arg;
- int opnum;
- int rc;
+ struct mslsa_LookupPrivName arg;
+ int opnum;
+ int rc;
if (lsa_handle == NULL || luid == NULL || name == NULL)
return (-1);
@@ -669,10 +1248,10 @@ DWORD
lsar_lookup_priv_display_name(mlsvc_handle_t *lsa_handle, char *name,
char *display_name, int display_len)
{
- struct mslsa_LookupPrivDisplayName arg;
- int opnum;
- size_t length;
- DWORD status;
+ struct mslsa_LookupPrivDisplayName arg;
+ int opnum;
+ size_t length;
+ DWORD status;
if (lsa_handle == NULL || name == NULL || display_name == NULL)
return (NT_STATUS_INVALID_PARAMETER);
@@ -706,179 +1285,12 @@ lsar_lookup_priv_display_name(mlsvc_handle_t *lsa_handle, char *name,
return (status);
}
-/*
- * lsar_lookup_sids2
- */
-uint32_t
-lsar_lookup_sids2(mlsvc_handle_t *lsa_handle, struct mslsa_sid *sid,
- smb_account_t *account)
-{
- struct lsar_lookup_sids2 arg;
- struct lsar_name_entry2 *name_entry;
- struct mslsa_lup_sid_entry sid_entry;
- struct mslsa_domain_entry *domain_entry;
- uint32_t status = NT_STATUS_SUCCESS;
- char *name;
- int opnum;
-
- if (lsa_handle == NULL || sid == NULL || account == NULL)
- return (NT_STATUS_INVALID_PARAMETER);
-
- bzero(account, sizeof (smb_account_t));
- opnum = LSARPC_OPNUM_LookupSids2;
-
- if (ndr_rpc_server_os(lsa_handle) != NATIVE_OS_WIN2000)
- return (NT_STATUS_REVISION_MISMATCH);
-
- bzero(&arg, sizeof (struct lsar_lookup_sids2));
- (void) memcpy(&arg.policy_handle, lsa_handle, sizeof (mslsa_handle_t));
-
- sid_entry.psid = sid;
- arg.lup_sid_table.n_entry = 1;
- arg.lup_sid_table.entries = &sid_entry;
- arg.lookup_level = MSLSA_LOOKUP_LEVEL_1;
- arg.requested_count = arg.lup_sid_table.n_entry;
-
- if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) {
- ndr_rpc_release(lsa_handle);
- return (NT_STATUS_INVALID_PARAMETER);
- }
-
- if (arg.status != NT_STATUS_SUCCESS) {
- ndr_rpc_status(lsa_handle, opnum, arg.status);
- ndr_rpc_release(lsa_handle);
- return (NT_SC_VALUE(arg.status));
- }
-
- if (arg.mapped_count == 0) {
- ndr_rpc_release(lsa_handle);
- return (NT_STATUS_NONE_MAPPED);
- }
-
- name_entry = &arg.name_table.entries[0];
- if (name_entry->domain_ix != 0) {
- ndr_rpc_release(lsa_handle);
- return (NT_STATUS_NONE_MAPPED);
- }
-
- name = (char *)name_entry->name.str;
- account->a_name = (name) ? strdup(name) : strdup("");
- account->a_type = name_entry->sid_name_use;
- account->a_sid = smb_sid_dup((smb_sid_t *)sid);
-
- domain_entry = &arg.domain_table->entries[0];
- if ((name = (char *)domain_entry->domain_name.str) != NULL)
- account->a_domain = strdup(name);
- account->a_domsid = smb_sid_dup((smb_sid_t *)domain_entry->domain_sid);
-
- if (!smb_account_validate(account)) {
- smb_account_free(account);
- status = NT_STATUS_NO_MEMORY;
- }
-
- ndr_rpc_release(lsa_handle);
- return (status);
-}
-
-
-/*
- * lsar_lookup_names2
- *
- * Windows NT expects the name length to exclude the terminating
- * wchar null but Windows 2000 insists that both the length and
- * the allosize include the wchar null. Windows NT doesn't care
- * whether or not the allosize includes or excludes the null char.
- *
- * As a precaution, I set the lookup level to 1 on Windows 2000
- * until I can do some more testing.
- *
- * Note that NT returns an error if the mapped_count is non-zero
- * when the RPC is called.
- *
- * It should be okay to lookup DOMAIN\Administrator in this function.
- */
-uint32_t
-lsar_lookup_names2(mlsvc_handle_t *lsa_handle, char *name, smb_account_t *info)
-{
- struct lsar_LookupNames2 arg;
- struct lsar_rid_entry2 *rid_entry;
- struct mslsa_domain_entry *domain_entry;
- lookup_name_table_t name_table;
- uint32_t status = NT_STATUS_SUCCESS;
- char *domname;
- size_t length;
- int opnum;
-
- if (lsa_handle == NULL || name == NULL || info == NULL)
- return (NT_STATUS_INVALID_PARAMETER);
-
- bzero(info, sizeof (smb_account_t));
-
- opnum = LSARPC_OPNUM_LookupNames2;
-
- if (ndr_rpc_server_os(lsa_handle) != NATIVE_OS_WIN2000)
- return (NT_STATUS_REVISION_MISMATCH);
-
- bzero(&arg, sizeof (struct lsar_LookupNames2));
- (void) memcpy(&arg.policy_handle, lsa_handle, sizeof (mslsa_handle_t));
- arg.unknown_sb2 = 0x00000002;
- arg.lookup_level = MSLSA_LOOKUP_LEVEL_1;
-
- arg.name_table = (struct mslsa_lup_name_table *)&name_table;
- name_table.n_entry = 1;
-
- length = smb_wcequiv_strlen(name) + sizeof (smb_wchar_t);
- name_table.name[0].length = length;
- name_table.name[0].allosize = length;
- name_table.name[0].str = (unsigned char *)name;
-
- if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) {
- ndr_rpc_release(lsa_handle);
- return (NT_STATUS_INVALID_PARAMETER);
- }
-
- if (arg.status != NT_STATUS_SUCCESS) {
- ndr_rpc_status(lsa_handle, opnum, arg.status);
- ndr_rpc_release(lsa_handle);
- return (NT_SC_VALUE(arg.status));
- }
-
- if (arg.mapped_count == 0) {
- ndr_rpc_release(lsa_handle);
- return (NT_STATUS_NONE_MAPPED);
- }
-
- rid_entry = &arg.translated_sids.rids[0];
- if (rid_entry->domain_index != 0) {
- ndr_rpc_release(lsa_handle);
- return (NT_STATUS_NONE_MAPPED);
- }
-
- domain_entry = &arg.domain_table->entries[0];
-
- info->a_type = rid_entry->sid_name_use;
- info->a_name = strdup(name);
- info->a_domsid = smb_sid_dup((smb_sid_t *)domain_entry->domain_sid);
- if ((domname = (char *)domain_entry->domain_name.str) != NULL)
- info->a_domain = strdup(domname);
- info->a_rid = rid_entry->rid;
- info->a_sid = smb_sid_splice(info->a_domsid, info->a_rid);
-
- if (!smb_account_validate(info)) {
- smb_account_free(info);
- status = NT_STATUS_NO_MEMORY;
- }
-
- ndr_rpc_release(lsa_handle);
- return (status);
-}
-
static void
lsar_set_trusted_domains_ex(struct mslsa_EnumTrustedDomainBufEx *enum_buf,
smb_trusted_domains_t *list)
{
- char sidstr[SMB_SID_STRSZ];
- int i;
+ char sidstr[SMB_SID_STRSZ];
+ int i;
if (list == NULL || enum_buf == NULL || enum_buf->entries_read == 0)
return;
@@ -908,8 +1320,8 @@ static void
lsar_set_trusted_domains(struct mslsa_EnumTrustedDomainBuf *enum_buf,
smb_trusted_domains_t *list)
{
- char sidstr[SMB_SID_STRSZ];
- int i;
+ char sidstr[SMB_SID_STRSZ];
+ int i;
if (list == NULL || enum_buf == NULL || enum_buf->entries_read == 0)
return;
@@ -929,3 +1341,15 @@ lsar_set_trusted_domains(struct mslsa_EnumTrustedDomainBuf *enum_buf,
"", 0, 0, 0, &list->td_domains[i]);
}
}
+
+static void
+smb_account_trace(const smb_account_t *info)
+{
+ char sidbuf[SMB_SID_STRSZ];
+
+ bzero(sidbuf, SMB_SID_STRSZ);
+ smb_sid_tostr(info->a_sid, sidbuf);
+
+ smb_tracef("%s %s %s %lu %s", info->a_domain, info->a_name,
+ sidbuf, info->a_rid, smb_sid_type2str(info->a_type));
+}
diff --git a/usr/src/lib/smbsrv/libmlsvc/common/lsar_open.c b/usr/src/lib/smbsrv/libmlsvc/common/lsar_open.c
deleted file mode 100644
index aefb2723e8..0000000000
--- a/usr/src/lib/smbsrv/libmlsvc/common/lsar_open.c
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-/*
- * Local Security Authority RPC (LSARPC) library interface functions for
- * open and close calls.
- */
-
-#include <stdio.h>
-#include <strings.h>
-
-#include <smbsrv/libsmb.h>
-#include <smbsrv/libmlsvc.h>
-#include <smbsrv/smbinfo.h>
-#include <smbsrv/ntaccess.h>
-#include <smbsrv/ntstatus.h>
-#include <lsalib.h>
-
-/*
- * lsar_open
- *
- * This is a wrapper round lsar_open_policy2 to ensure that we connect
- * using the appropriate domain information.
- *
- * If username argument is NULL, an anonymous connection will be established.
- * Otherwise, an authenticated connection will be established.
- *
- * On success 0 is returned. Otherwise a -ve error code.
- */
-int lsar_open(char *server, char *domain, char *username,
- mlsvc_handle_t *domain_handle)
-{
- if (server == NULL || domain == NULL)
- return (-1);
-
- if (username == NULL)
- username = MLSVC_ANON_USER;
-
- return (lsar_open_policy2(server, domain, username, domain_handle));
-}
-
-/*
- * lsar_open_policy2
- *
- * Obtain an LSA policy handle. A policy handle is required to access
- * LSA resources on a remote server. The server name supplied here does
- * not need the double backslash prefix; it is added here. Call this
- * function via lsar_open to ensure that the appropriate connection is
- * in place.
- *
- * I'm not sure if it makes a difference whether we use GENERIC_EXECUTE
- * or STANDARD_RIGHTS_EXECUTE. For a long time I used the standard bit
- * and then I added the generic bit while working on privileges because
- * NT sets that bit. I don't think it matters.
- *
- * Returns 0 on success. Otherwise non-zero to indicate a failure.
- */
-int
-lsar_open_policy2(char *server, char *domain, char *username,
- mlsvc_handle_t *lsa_handle)
-{
- struct mslsa_OpenPolicy2 arg;
- int opnum;
- int len;
- int rc;
-
- rc = ndr_rpc_bind(lsa_handle, server, domain, username, "LSARPC");
- if (rc != 0)
- return (-1);
-
- opnum = LSARPC_OPNUM_OpenPolicy2;
- bzero(&arg, sizeof (struct mslsa_OpenPolicy2));
-
- len = strlen(server) + 4;
- arg.servername = ndr_rpc_malloc(lsa_handle, len);
- if (arg.servername == NULL) {
- ndr_rpc_unbind(lsa_handle);
- return (-1);
- }
-
- (void) snprintf((char *)arg.servername, len, "\\\\%s", server);
- arg.attributes.length = sizeof (struct mslsa_object_attributes);
-
- if (ndr_rpc_server_os(lsa_handle) == NATIVE_OS_WIN2000) {
- arg.desiredAccess = MAXIMUM_ALLOWED;
- } else {
- arg.desiredAccess = GENERIC_EXECUTE
- | STANDARD_RIGHTS_EXECUTE
- | POLICY_VIEW_LOCAL_INFORMATION
- | POLICY_LOOKUP_NAMES;
- }
-
- if ((rc = ndr_rpc_call(lsa_handle, opnum, &arg)) != 0) {
- ndr_rpc_unbind(lsa_handle);
- return (-1);
- }
-
- if (arg.status != 0) {
- rc = -1;
- } else {
- (void) memcpy(&lsa_handle->handle, &arg.domain_handle,
- sizeof (ndr_hdid_t));
-
- if (ndr_is_null_handle(lsa_handle))
- rc = -1;
- }
-
- ndr_rpc_release(lsa_handle);
-
- if (rc != 0)
- ndr_rpc_unbind(lsa_handle);
- return (rc);
-}
-
-/*
- * lsar_open_account
- *
- * Obtain an LSA account handle. The lsa_handle must be a valid handle
- * obtained via lsar_open_policy2. The main thing to remember here is
- * to set up the context in the lsa_account_handle. I'm not sure what
- * the requirements are for desired access. Some values require admin
- * access.
- *
- * Returns 0 on success. Otherwise non-zero to indicate a failure.
- */
-int
-lsar_open_account(mlsvc_handle_t *lsa_handle, struct mslsa_sid *sid,
- mlsvc_handle_t *lsa_account_handle)
-{
- struct mslsa_OpenAccount arg;
- int opnum;
- int rc;
-
- if (ndr_is_null_handle(lsa_handle) || sid == NULL)
- return (-1);
-
- opnum = LSARPC_OPNUM_OpenAccount;
- bzero(&arg, sizeof (struct mslsa_OpenAccount));
-
- (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t));
- arg.sid = sid;
- arg.access_mask = STANDARD_RIGHTS_REQUIRED
-#if 0
- | POLICY_VIEW_AUDIT_INFORMATION
- | POLICY_GET_PRIVATE_INFORMATION
- | POLICY_TRUST_ADMIN
-#endif
- | POLICY_VIEW_LOCAL_INFORMATION;
-
- if ((rc = ndr_rpc_call(lsa_handle, opnum, &arg)) != 0)
- return (-1);
-
- if (arg.status != 0) {
- rc = -1;
- } else {
- ndr_inherit_handle(lsa_account_handle, lsa_handle);
-
- (void) memcpy(&lsa_account_handle->handle,
- &arg.account_handle, sizeof (ndr_hdid_t));
-
- if (ndr_is_null_handle(lsa_account_handle))
- rc = -1;
- }
-
- ndr_rpc_release(lsa_handle);
- return (rc);
-}
-
-/*
- * lsar_close
- *
- * Close the LSA connection associated with the handle. The lsa_handle
- * must be a valid handle obtained via a call to lsar_open_policy2 or
- * lsar_open_account. On success the handle will be zeroed out to
- * ensure that it is not used again. If this is the top level handle
- * (i.e. the one obtained via lsar_open_policy2) the pipe is closed.
- *
- * Returns 0 on success. Otherwise non-zero to indicate a failure.
- */
-int
-lsar_close(mlsvc_handle_t *lsa_handle)
-{
- struct mslsa_CloseHandle arg;
- int opnum;
-
- if (ndr_is_null_handle(lsa_handle))
- return (-1);
-
- opnum = LSARPC_OPNUM_CloseHandle;
- bzero(&arg, sizeof (struct mslsa_CloseHandle));
- (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t));
-
- (void) ndr_rpc_call(lsa_handle, opnum, &arg);
- ndr_rpc_release(lsa_handle);
-
- if (ndr_is_bind_handle(lsa_handle))
- ndr_rpc_unbind(lsa_handle);
-
- bzero(lsa_handle, sizeof (mlsvc_handle_t));
- return (0);
-}
diff --git a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_lsa.c b/usr/src/lib/smbsrv/libmlsvc/common/lsar_svc.c
index 058811cb6e..7e9a3aa0e0 100644
--- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_lsa.c
+++ b/usr/src/lib/smbsrv/libmlsvc/common/lsar_svc.c
@@ -24,7 +24,7 @@
*/
/*
- * Local Security Authority RPC (LSARPC) server-side interface definition.
+ * Local Security Authority RPC (LSAR) server-side interface.
*/
#include <unistd.h>
@@ -55,26 +55,29 @@ static int lsarpc_key_account;
static int lsarpc_call_stub(ndr_xa_t *mxa);
-static int lsarpc_s_CloseHandle(void *arg, ndr_xa_t *);
-static int lsarpc_s_QuerySecurityObject(void *arg, ndr_xa_t *);
-static int lsarpc_s_EnumAccounts(void *arg, ndr_xa_t *);
-static int lsarpc_s_EnumTrustedDomain(void *arg, ndr_xa_t *);
-static int lsarpc_s_EnumTrustedDomainsEx(void *arg, ndr_xa_t *);
-static int lsarpc_s_OpenAccount(void *arg, ndr_xa_t *);
-static int lsarpc_s_EnumPrivsAccount(void *arg, ndr_xa_t *);
-static int lsarpc_s_LookupPrivValue(void *arg, ndr_xa_t *);
-static int lsarpc_s_LookupPrivName(void *arg, ndr_xa_t *);
-static int lsarpc_s_LookupPrivDisplayName(void *arg, ndr_xa_t *);
+static int lsarpc_s_CloseHandle(void *, ndr_xa_t *);
+static int lsarpc_s_QuerySecurityObject(void *, ndr_xa_t *);
+static int lsarpc_s_EnumAccounts(void *, ndr_xa_t *);
+static int lsarpc_s_EnumTrustedDomain(void *, ndr_xa_t *);
+static int lsarpc_s_EnumTrustedDomainsEx(void *, ndr_xa_t *);
+static int lsarpc_s_OpenAccount(void *, ndr_xa_t *);
+static int lsarpc_s_EnumPrivsAccount(void *, ndr_xa_t *);
+static int lsarpc_s_LookupPrivValue(void *, ndr_xa_t *);
+static int lsarpc_s_LookupPrivName(void *, ndr_xa_t *);
+static int lsarpc_s_LookupPrivDisplayName(void *, ndr_xa_t *);
static int lsarpc_s_CreateSecret(void *, ndr_xa_t *);
static int lsarpc_s_OpenSecret(void *, ndr_xa_t *);
-static int lsarpc_s_QueryInfoPolicy(void *arg, ndr_xa_t *);
-static int lsarpc_s_OpenDomainHandle(void *arg, ndr_xa_t *);
-static int lsarpc_s_OpenDomainHandle(void *arg, ndr_xa_t *);
-static int lsarpc_s_LookupSids(void *arg, ndr_xa_t *);
-static int lsarpc_s_LookupNames(void *arg, ndr_xa_t *);
-static int lsarpc_s_GetConnectedUser(void *arg, ndr_xa_t *);
-static int lsarpc_s_LookupSids2(void *arg, ndr_xa_t *);
-static int lsarpc_s_LookupNames2(void *arg, ndr_xa_t *);
+static int lsarpc_s_QueryInfoPolicy(void *, ndr_xa_t *);
+static int lsarpc_s_OpenDomainHandle(void *, ndr_xa_t *);
+static int lsarpc_s_OpenDomainHandle(void *, ndr_xa_t *);
+static int lsarpc_s_LookupSids(void *, ndr_xa_t *);
+static int lsarpc_s_LookupNames(void *, ndr_xa_t *);
+static int lsarpc_s_GetConnectedUser(void *, ndr_xa_t *);
+static int lsarpc_s_LookupSids2(void *, ndr_xa_t *);
+static int lsarpc_s_LookupSids3(void *, ndr_xa_t *);
+static int lsarpc_s_LookupNames2(void *, ndr_xa_t *);
+static int lsarpc_s_LookupNames3(void *, ndr_xa_t *);
+static int lsarpc_s_LookupNames4(void *, ndr_xa_t *);
static DWORD lsarpc_s_PrimaryDomainInfo(struct mslsa_PrimaryDomainInfo *,
ndr_xa_t *);
@@ -103,7 +106,10 @@ static ndr_stub_table_t lsarpc_stub_table[] = {
{ lsarpc_s_LookupNames, LSARPC_OPNUM_LookupNames },
{ lsarpc_s_GetConnectedUser, LSARPC_OPNUM_GetConnectedUser },
{ lsarpc_s_LookupSids2, LSARPC_OPNUM_LookupSids2 },
+ { lsarpc_s_LookupSids3, LSARPC_OPNUM_LookupSids3 },
{ lsarpc_s_LookupNames2, LSARPC_OPNUM_LookupNames2 },
+ { lsarpc_s_LookupNames3, LSARPC_OPNUM_LookupNames3 },
+ { lsarpc_s_LookupNames4, LSARPC_OPNUM_LookupNames4 },
{0}
};
@@ -214,7 +220,7 @@ lsarpc_s_QuerySecurityObject(void *arg, ndr_xa_t *mxa)
* multiple enumeration calls to obtain the complete list of SIDs.
* It should be set to 0 on the first call and passed unchanged on
* subsequent calls until there are no more accounts - the server will
- * return NT_SC_WARNING(MLSVC_NO_MORE_DATA).
+ * return NT_SC_WARNING(NT_STATUS_NO_MORE_DATA).
*
* For now just set the status to access-denied. Note that we still have
* to provide a valid address for enum_buf because it's a reference and
@@ -251,7 +257,7 @@ lsarpc_s_EnumAccounts(void *arg, ndr_xa_t *mxa)
* support multiple enumeration calls to obtain the complete list.
* It should be set to 0 on the first call and passed unchanged on
* subsequent calls until there are no more accounts - the server will
- * return NT_SC_WARNING(MLSVC_NO_MORE_DATA).
+ * return NT_SC_WARNING(NT_STATUS_NO_MORE_DATA).
*
* For now just set the status to access-denied. Note that we still have
* to provide a valid address for enum_buf because it's a reference and
@@ -286,7 +292,7 @@ lsarpc_s_EnumTrustedDomain(void *arg, ndr_xa_t *mxa)
* support multiple enumeration calls to obtain the complete list.
* It should be set to 0 on the first call and passed unchanged on
* subsequent calls until there are no more accounts - the server will
- * return NT_SC_WARNING(MLSVC_NO_MORE_DATA).
+ * return NT_SC_WARNING(NT_STATUS_NO_MORE_DATA).
*
* For now just set the status to access-denied. Note that we still have
* to provide a valid address for enum_buf because it's a reference and
@@ -506,13 +512,8 @@ lsarpc_s_OpenSecret(void *arg, ndr_xa_t *mxa)
/*
* lsarpc_s_GetConnectedUser
*
- * This is still guesswork. Netmon doesn't know about this
- * call and I'm not really sure what it is intended to achieve.
- * Another packet capture application, Ethereal, calls this RPC as
- * GetConnectedUser.
- * We will receive our own hostname in the request and it appears
- * we should respond with an account name and the domain name of connected
- * user from the client that makes this call.
+ * Return the account name and NetBIOS domain name for the user making
+ * the request. The hostname field should be ignored by the server.
*/
static int
lsarpc_s_GetConnectedUser(void *arg, ndr_xa_t *mxa)
@@ -781,6 +782,10 @@ lsarpc_s_LookupNames(void *arg, ndr_xa_t *mxa)
* table and make the name entry point at the appropriate domain table
* entry.
*
+ *
+ * This RPC should behave as if LookupOptions is LSA_LOOKUP_OPT_ALL and
+ * ClientRevision is LSA_CLIENT_REVISION_NT.
+ *
* On success return 0. Otherwise return an RPC specific error code.
*/
static int
@@ -925,6 +930,8 @@ lsarpc_s_UpdateDomainTable(ndr_xa_t *mxa,
*
* Other than the use of lsar_lookup_sids2 and lsar_name_entry2, this
* is identical to lsarpc_s_LookupSids.
+ *
+ * Ignore lookup_level, it is reserved and should be zero.
*/
static int
lsarpc_s_LookupSids2(void *arg, ndr_xa_t *mxa)
@@ -1005,10 +1012,28 @@ lookup_sid_failed:
}
/*
+ * LookupSids3 is only valid on domain controllers.
+ * Other servers must return NT_STATUS_INVALID_SERVER_STATE.
+ */
+/*ARGSUSED*/
+static int
+lsarpc_s_LookupSids3(void *arg, ndr_xa_t *mxa)
+{
+ struct lsar_lookup_sids3 *param = arg;
+
+ bzero(param, sizeof (struct lsar_lookup_sids3));
+ param->status = NT_SC_ERROR(NT_STATUS_INVALID_SERVER_STATE);
+ return (NDR_DRC_OK);
+}
+
+/*
* lsarpc_s_LookupNames2
*
* Other than the use of lsar_LookupNames2 and lsar_rid_entry2, this
* is identical to lsarpc_s_LookupNames.
+ *
+ * If LookupOptions contains LSA_LOOKUP_OPT_LOCAL and LookupLevel is not
+ * LSA_LOOKUP_WKSTA, return STATUS_INVALID_PARAMETER.
*/
static int
lsarpc_s_LookupNames2(void *arg, ndr_xa_t *mxa)
@@ -1025,6 +1050,13 @@ lsarpc_s_LookupNames2(void *arg, ndr_xa_t *mxa)
if (param->name_table->n_entry != 1)
return (NDR_DRC_FAULT_PARAM_0_UNIMPLEMENTED);
+ if ((param->lookup_options & LSA_LOOKUP_OPT_LOCAL) &&
+ param->lookup_level != LSA_LOOKUP_WKSTA) {
+ bzero(param, sizeof (struct lsar_LookupNames2));
+ param->status = NT_SC_ERROR(NT_STATUS_INVALID_PARAMETER);
+ return (NDR_DRC_OK);
+ }
+
rids = NDR_NEW(mxa, struct lsar_rid_entry2);
domain_table = NDR_NEW(mxa, struct mslsa_domain_table);
domain_entry = NDR_NEW(mxa, struct mslsa_domain_entry);
@@ -1081,6 +1113,105 @@ lsarpc_s_LookupNames2(void *arg, ndr_xa_t *mxa)
return (NDR_DRC_OK);
}
+/*
+ * Other than the use of lsar_LookupNames2 and lsar_rid_entry2, this
+ * is identical to lsarpc_s_LookupNames.
+ *
+ * If LookupOptions contains LSA_LOOKUP_OPT_LOCAL and LookupLevel is not
+ * LSA_LOOKUP_WKSTA, return STATUS_INVALID_PARAMETER.
+ */
+static int
+lsarpc_s_LookupNames3(void *arg, ndr_xa_t *mxa)
+{
+ struct lsar_LookupNames3 *param = arg;
+ struct lsar_translated_sid_ex2 *sids;
+ struct mslsa_domain_table *domain_table;
+ struct mslsa_domain_entry *domain_entry;
+ smb_account_t account;
+ uint32_t status;
+ char *accname;
+ int rc = 0;
+
+ if (param->name_table->n_entry != 1)
+ return (NDR_DRC_FAULT_PARAM_0_UNIMPLEMENTED);
+
+ if ((param->lookup_options & LSA_LOOKUP_OPT_LOCAL) &&
+ param->lookup_level != LSA_LOOKUP_WKSTA) {
+ bzero(param, sizeof (struct lsar_LookupNames3));
+ param->status = NT_SC_ERROR(NT_STATUS_INVALID_PARAMETER);
+ return (NDR_DRC_OK);
+ }
+
+ sids = NDR_NEW(mxa, struct lsar_translated_sid_ex2);
+ domain_table = NDR_NEW(mxa, struct mslsa_domain_table);
+ domain_entry = NDR_NEW(mxa, struct mslsa_domain_entry);
+
+ if (sids == NULL || domain_table == NULL || domain_entry == NULL) {
+ bzero(param, sizeof (struct lsar_LookupNames3));
+ param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
+ return (NDR_DRC_OK);
+ }
+
+ accname = (char *)param->name_table->names->str;
+ status = lsa_lookup_name(accname, SidTypeUnknown, &account);
+ if (status != NT_STATUS_SUCCESS) {
+ bzero(param, sizeof (struct lsar_LookupNames3));
+ param->status = NT_SC_ERROR(status);
+ return (NDR_DRC_OK);
+ }
+
+ /*
+ * Set up the SID table.
+ */
+ bzero(sids, sizeof (struct lsar_translated_sid_ex2));
+ sids[0].sid_name_use = account.a_type;
+ sids[0].sid = (struct mslsa_sid *)NDR_SIDDUP(mxa, account.a_sid);
+ sids[0].domain_index = 0;
+ param->translated_sids.n_entry = 1;
+ param->translated_sids.sids = sids;
+
+ /*
+ * Set up the domain table.
+ */
+ domain_table->entries = domain_entry;
+ domain_table->n_entry = 1;
+ domain_table->max_n_entry = MLSVC_DOMAIN_MAX;
+
+ rc = NDR_MSTRING(mxa, account.a_domain,
+ (ndr_mstring_t *)&domain_entry->domain_name);
+
+ domain_entry->domain_sid =
+ (struct mslsa_sid *)NDR_SIDDUP(mxa, account.a_domsid);
+
+ if (rc == -1 || domain_entry->domain_sid == NULL) {
+ smb_account_free(&account);
+ bzero(param, sizeof (struct lsar_LookupNames3));
+ param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
+ return (NDR_DRC_OK);
+ }
+
+ param->domain_table = domain_table;
+ param->mapped_count = 1;
+ param->status = NT_STATUS_SUCCESS;
+
+ smb_account_free(&account);
+ return (NDR_DRC_OK);
+}
+
+/*
+ * LookupNames4 is only valid on domain controllers.
+ * Other servers must return NT_STATUS_INVALID_SERVER_STATE.
+ */
+/*ARGSUSED*/
+static int
+lsarpc_s_LookupNames4(void *arg, ndr_xa_t *mxa)
+{
+ struct lsar_LookupNames4 *param = arg;
+
+ bzero(param, sizeof (struct lsar_LookupNames4));
+ param->status = NT_SC_ERROR(NT_STATUS_INVALID_SERVER_STATE);
+ return (NDR_DRC_OK);
+}
/*
* There is a bug in the way that ndrgen and the marshalling code handles
diff --git a/usr/src/lib/smbsrv/libmlsvc/common/mapfile-vers b/usr/src/lib/smbsrv/libmlsvc/common/mapfile-vers
index 59bd319ef3..1855b2ea66 100644
--- a/usr/src/lib/smbsrv/libmlsvc/common/mapfile-vers
+++ b/usr/src/lib/smbsrv/libmlsvc/common/mapfile-vers
@@ -41,19 +41,18 @@
SUNWprivate {
global:
dssetup_clear_domain_info;
+ lsa_lookup_name;
+ lsa_lookup_sid;
mlsvc_disconnect;
mlsvc_fini;
mlsvc_init;
mlsvc_join;
- mlsvc_lookup_name;
- mlsvc_lookup_sid;
mlsvc_netlogon;
smb_autohome_add;
smb_autohome_remove;
smb_locate_dc;
smb_logon;
smb_shr_add;
- smb_shr_chkname;
smb_shr_count;
smb_shr_exec;
smb_shr_get;
diff --git a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_client.c b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_client.c
index 9194ec7871..6ef7897fe1 100644
--- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_client.c
+++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_client.c
@@ -38,6 +38,7 @@
#include <smbsrv/libsmbrdr.h>
#include <smbsrv/libmlrpc.h>
#include <smbsrv/libmlsvc.h>
+#include <smbsrv/ndl/srvsvc.ndl>
/*
* Server info cache entry expiration in seconds.
@@ -135,7 +136,6 @@ ndr_rpc_bind(mlsvc_handle_t *handle, char *server, char *domain,
ndr_client_t *clnt;
ndr_service_t *svc;
srvsvc_server_info_t svinfo;
- int remote_os;
int fid;
int rc;
@@ -151,14 +151,17 @@ ndr_rpc_bind(mlsvc_handle_t *handle, char *server, char *domain,
* servers will be Windows 2000 or later.
* Don't lookup the svinfo if this is a SRVSVC request
* because the SRVSVC is used to get the server info.
- * None of the SRVSVC calls depend on the remote OS.
+ * None of the SRVSVC calls depend on the server info.
*/
- remote_os = NATIVE_OS_WIN2000;
+ bzero(&svinfo, sizeof (srvsvc_server_info_t));
+ svinfo.sv_platform_id = SV_PLATFORM_ID_NT;
+ svinfo.sv_version_major = 5;
+ svinfo.sv_version_minor = 0;
+ svinfo.sv_type = SV_TYPE_DEFAULT;
+ svinfo.sv_os = NATIVE_OS_WIN2000;
- if (strcasecmp(service, "SRVSVC") != 0) {
- if (ndr_svinfo_lookup(server, domain, &svinfo) == 0)
- remote_os = svinfo.sv_os;
- }
+ if (strcasecmp(service, "SRVSVC") != 0)
+ (void) ndr_svinfo_lookup(server, domain, &svinfo);
if ((clnt = malloc(sizeof (ndr_client_t))) == NULL)
return (-1);
@@ -185,7 +188,7 @@ ndr_rpc_bind(mlsvc_handle_t *handle, char *server, char *domain,
bzero(&handle->handle, sizeof (ndr_hdid_t));
handle->clnt = clnt;
- handle->remote_os = remote_os;
+ bcopy(&svinfo, &handle->svinfo, sizeof (srvsvc_server_info_t));
if (ndr_rpc_get_heap(handle) == NULL) {
free(clnt);
@@ -248,6 +251,12 @@ ndr_rpc_call(mlsvc_handle_t *handle, int opnum, void *params)
rc = ndr_clnt_call(clnt->binding, opnum, params);
+ /*
+ * Always clear the nonull flag to ensure
+ * it is not applied to subsequent calls.
+ */
+ clnt->nonull = B_FALSE;
+
if (NDR_DRC_IS_FAULT(rc)) {
ndr_rpc_release(handle);
return (-1);
@@ -257,12 +266,30 @@ ndr_rpc_call(mlsvc_handle_t *handle, int opnum, void *params)
}
/*
- * Returns the Native-OS of the RPC server.
+ * Outgoing strings should not be null terminated.
+ */
+void
+ndr_rpc_set_nonull(mlsvc_handle_t *handle)
+{
+ handle->clnt->nonull = B_TRUE;
+}
+
+/*
+ * Return a reference to the server info.
+ */
+const srvsvc_server_info_t *
+ndr_rpc_server_info(mlsvc_handle_t *handle)
+{
+ return (&handle->svinfo);
+}
+
+/*
+ * Return the RPC server OS level.
*/
uint32_t
ndr_rpc_server_os(mlsvc_handle_t *handle)
{
- return (handle->remote_os);
+ return (handle->svinfo.sv_os);
}
/*
@@ -366,7 +393,7 @@ void
ndr_inherit_handle(mlsvc_handle_t *child, mlsvc_handle_t *parent)
{
child->clnt = parent->clnt;
- child->remote_os = parent->remote_os;
+ bcopy(&parent->svinfo, &child->svinfo, sizeof (srvsvc_server_info_t));
}
void
@@ -401,9 +428,10 @@ ndr_rpc_status(mlsvc_handle_t *handle, int opnum, DWORD status)
static int
ndr_xa_init(ndr_client_t *clnt, ndr_xa_t *mxa)
{
- ndr_stream_t *recv_nds = &mxa->recv_nds;
- ndr_stream_t *send_nds = &mxa->send_nds;
- ndr_heap_t *heap = clnt->heap;
+ ndr_stream_t *recv_nds = &mxa->recv_nds;
+ ndr_stream_t *send_nds = &mxa->send_nds;
+ ndr_heap_t *heap = clnt->heap;
+ int rc;
if (heap == NULL) {
if ((heap = ndr_heap_create()) == NULL)
@@ -414,9 +442,23 @@ ndr_xa_init(ndr_client_t *clnt, ndr_xa_t *mxa)
mxa->heap = heap;
- nds_initialize(send_nds, 0, NDR_MODE_CALL_SEND, heap);
- nds_initialize(recv_nds, NDR_PDU_SIZE_HINT_DEFAULT,
- NDR_MODE_RETURN_RECV, heap);
+ rc = nds_initialize(send_nds, 0, NDR_MODE_CALL_SEND, heap);
+ if (rc == 0)
+ rc = nds_initialize(recv_nds, NDR_PDU_SIZE_HINT_DEFAULT,
+ NDR_MODE_RETURN_RECV, heap);
+
+ if (rc != 0) {
+ nds_destruct(&mxa->recv_nds);
+ nds_destruct(&mxa->send_nds);
+ ndr_heap_destroy(mxa->heap);
+ mxa->heap = NULL;
+ clnt->heap = NULL;
+ return (-1);
+ }
+
+ if (clnt->nonull)
+ NDS_SETF(send_nds, NDS_F_NONULL);
+
return (0);
}
@@ -530,6 +572,9 @@ ndr_xa_release(ndr_client_t *clnt)
* Lookup platform, type and version information about a server.
* If the cache doesn't already contain the data, contact the server and
* cache the response before returning the server info to the caller.
+ *
+ * We don't provide the name or comment for now, which avoids the need
+ * to deal with unnecessary memory management.
*/
static int
ndr_svinfo_lookup(char *server, char *domain, srvsvc_server_info_t *svinfo)
@@ -549,6 +594,8 @@ ndr_svinfo_lookup(char *server, char *domain, srvsvc_server_info_t *svinfo)
if (ndr_svinfo_match(server, domain, svi)) {
bcopy(&svi->svi_svinfo, svinfo,
sizeof (srvsvc_server_info_t));
+ svinfo->sv_name = NULL;
+ svinfo->sv_comment = NULL;
(void) mutex_unlock(&ndr_svlist.svl_mtx);
return (0);
}
@@ -572,6 +619,8 @@ ndr_svinfo_lookup(char *server, char *domain, srvsvc_server_info_t *svinfo)
(void) strlcpy(svi->svi_domain, domain, MAXNAMELEN);
list_insert_tail(&ndr_svlist.svl_list, svi);
bcopy(&svi->svi_svinfo, svinfo, sizeof (srvsvc_server_info_t));
+ svinfo->sv_name = NULL;
+ svinfo->sv_comment = NULL;
(void) mutex_unlock(&ndr_svlist.svl_mtx);
return (0);
}
diff --git a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_util.c b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_util.c
index ac4cda132f..80f26918a4 100644
--- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_util.c
+++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_util.c
@@ -53,60 +53,6 @@ extern int netr_open(char *, char *, mlsvc_handle_t *);
extern int netr_close(mlsvc_handle_t *);
extern DWORD netlogon_auth(char *, mlsvc_handle_t *, DWORD);
-/*
- * mlsvc_lookup_name
- *
- * This is just a wrapper for lsa_lookup_name.
- *
- * The memory for the sid is allocated using malloc so the caller should
- * call free when it is no longer required.
- */
-uint32_t
-mlsvc_lookup_name(char *name, smb_sid_t **sid, uint16_t *sid_type)
-{
- smb_account_t account;
- uint32_t status;
-
- status = lsa_lookup_name(name, *sid_type, &account);
- if (status == NT_STATUS_SUCCESS) {
- *sid = account.a_sid;
- account.a_sid = NULL;
- *sid_type = account.a_type;
- smb_account_free(&account);
- }
-
- return (status);
-}
-
-/*
- * mlsvc_lookup_sid
- *
- * This is just a wrapper for lsa_lookup_sid.
- *
- * The allocated memory for the returned name must be freed by caller upon
- * successful return.
- */
-uint32_t
-mlsvc_lookup_sid(smb_sid_t *sid, char **name)
-{
- smb_account_t ainfo;
- uint32_t status;
- int namelen;
-
- if ((status = lsa_lookup_sid(sid, &ainfo)) == NT_STATUS_SUCCESS) {
- namelen = strlen(ainfo.a_domain) + strlen(ainfo.a_name) + 2;
- if ((*name = malloc(namelen)) != NULL)
- (void) snprintf(*name, namelen, "%s\\%s",
- ainfo.a_domain, ainfo.a_name);
- else
- status = NT_STATUS_NO_MEMORY;
-
- smb_account_free(&ainfo);
- }
-
- return (status);
-}
-
DWORD
mlsvc_netlogon(char *server, char *domain)
{
diff --git a/usr/src/lib/smbsrv/libmlsvc/common/samlib.c b/usr/src/lib/smbsrv/libmlsvc/common/samlib.c
index 254102b85d..1c659bcc16 100644
--- a/usr/src/lib/smbsrv/libmlsvc/common/samlib.c
+++ b/usr/src/lib/smbsrv/libmlsvc/common/samlib.c
@@ -138,7 +138,7 @@ sam_create_account(char *server, char *domain_name, char *account_name,
if (status == NT_STATUS_SUCCESS) {
(void) samr_query_user_info(&user_handle,
- SAMR_QUERY_USER_UNKNOWN16, &sui);
+ SAMR_QUERY_USER_CONTROL_INFO, &sui);
(void) samr_get_user_pwinfo(&user_handle);
(void) samr_set_user_info(&user_handle);
diff --git a/usr/src/lib/smbsrv/libmlsvc/common/samr_open.c b/usr/src/lib/smbsrv/libmlsvc/common/samr_clnt.c
index d29e7d3d64..3236ab5381 100644
--- a/usr/src/lib/smbsrv/libmlsvc/common/samr_open.c
+++ b/usr/src/lib/smbsrv/libmlsvc/common/samr_clnt.c
@@ -24,18 +24,21 @@
*/
/*
- * Security Access Manager RPC (SAMR) library interface functions for
- * connect, open and close calls. The SAM is a hierarchical database.
- * If you want to talk to the SAM you need a SAM handle, if you want
- * to work with a domain, you need to use the SAM handle to obtain a
- * domain handle. Then you can use the domain handle to obtain a user
- * handle etc. Be careful about returning null handles to the
- * application. Use of a null handle may crash the domain controller
- * if you attempt to use it.
+ * Security Accounts Manager RPC (SAMR) client-side interface.
+ *
+ * The SAM is a hierarchical database:
+ * - If you want to talk to the SAM you need a SAM handle.
+ * - If you want to work with a domain, use the SAM handle.
+ * to obtain a domain handle.
+ * - Use domain handles to obtain user handles etc.
+ *
+ * Be careful about returning null handles to the application. Use of a
+ * null handle may crash the domain controller if you attempt to use it.
*/
#include <stdio.h>
#include <strings.h>
+#include <stdlib.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/param.h>
@@ -46,6 +49,7 @@
#include <smbsrv/smbinfo.h>
#include <smbsrv/ntstatus.h>
#include <smbsrv/ntaccess.h>
+#include <smbsrv/smb_sid.h>
#include <samlib.h>
/*LINTED E_STATIC_UNUSED*/
@@ -57,6 +61,12 @@ static DWORD samr_connect4(char *, char *, char *, DWORD, mlsvc_handle_t *);
typedef DWORD (*samr_connop_t)(char *, char *, char *, DWORD,
mlsvc_handle_t *);
+static int samr_setup_user_info(WORD, struct samr_QueryUserInfo *,
+ union samr_user_info *);
+static void samr_set_user_unknowns(struct samr_SetUserInfo23 *);
+static void samr_set_user_logon_hours(struct samr_SetUserInfo *);
+static int samr_set_user_password(unsigned char *, BYTE *);
+
/*
* samr_open
*
@@ -606,3 +616,479 @@ samr_create_user(mlsvc_handle_t *domain_handle, char *username,
ndr_rpc_release(domain_handle);
return (status);
}
+
+/*
+ * samr_lookup_domain
+ *
+ * Lookup up the domain SID for the specified domain name. The handle
+ * should be one returned from samr_connect. The allocated memory for
+ * the returned SID must be freed by caller.
+ */
+smb_sid_t *
+samr_lookup_domain(mlsvc_handle_t *samr_handle, char *domain_name)
+{
+ struct samr_LookupDomain arg;
+ smb_sid_t *domsid = NULL;
+ int opnum;
+ size_t length;
+
+ if (ndr_is_null_handle(samr_handle) || domain_name == NULL)
+ return (NULL);
+
+ opnum = SAMR_OPNUM_LookupDomain;
+ bzero(&arg, sizeof (struct samr_LookupDomain));
+
+ (void) memcpy(&arg.handle, &samr_handle->handle,
+ sizeof (samr_handle_t));
+
+ length = smb_wcequiv_strlen(domain_name);
+ if (ndr_rpc_server_os(samr_handle) == NATIVE_OS_WIN2000)
+ length += sizeof (smb_wchar_t);
+
+ arg.domain_name.length = length;
+ arg.domain_name.allosize = length;
+ arg.domain_name.str = (unsigned char *)domain_name;
+
+ if (ndr_rpc_call(samr_handle, opnum, &arg) == 0)
+ domsid = smb_sid_dup((smb_sid_t *)arg.sid);
+
+ ndr_rpc_release(samr_handle);
+ return (domsid);
+}
+
+/*
+ * samr_enum_local_domains
+ *
+ * Get the list of local domains supported by a server.
+ *
+ * Returns NT status codes.
+ */
+DWORD
+samr_enum_local_domains(mlsvc_handle_t *samr_handle)
+{
+ struct samr_EnumLocalDomain arg;
+ int opnum;
+ DWORD status;
+
+ if (ndr_is_null_handle(samr_handle))
+ return (NT_STATUS_INVALID_PARAMETER);
+
+ opnum = SAMR_OPNUM_EnumLocalDomains;
+ bzero(&arg, sizeof (struct samr_EnumLocalDomain));
+
+ (void) memcpy(&arg.handle, &samr_handle->handle,
+ sizeof (samr_handle_t));
+ arg.enum_context = 0;
+ arg.max_length = 0x00002000; /* Value used by NT */
+
+ if (ndr_rpc_call(samr_handle, opnum, &arg) != 0) {
+ status = NT_STATUS_INVALID_PARAMETER;
+ } else {
+ status = NT_SC_VALUE(arg.status);
+
+ /*
+ * Handle none-mapped status quietly.
+ */
+ if (status != NT_STATUS_NONE_MAPPED)
+ ndr_rpc_status(samr_handle, opnum, arg.status);
+ }
+
+ ndr_rpc_release(samr_handle);
+ return (status);
+}
+
+/*
+ * samr_lookup_domain_names
+ *
+ * Lookup up the given name in the domain specified by domain_handle.
+ * Upon a successful lookup the information is returned in the account
+ * arg and caller must free allocated memories by calling smb_account_free().
+ *
+ * Returns NT status codes.
+ */
+uint32_t
+samr_lookup_domain_names(mlsvc_handle_t *domain_handle, char *name,
+ smb_account_t *account)
+{
+ struct samr_LookupNames arg;
+ int opnum;
+ uint32_t status;
+ size_t length;
+
+ if (ndr_is_null_handle(domain_handle) ||
+ name == NULL || account == NULL) {
+ return (NT_STATUS_INVALID_PARAMETER);
+ }
+
+ bzero(account, sizeof (smb_account_t));
+ opnum = SAMR_OPNUM_LookupNames;
+ bzero(&arg, sizeof (struct samr_LookupNames));
+
+ (void) memcpy(&arg.handle, &domain_handle->handle,
+ sizeof (samr_handle_t));
+ arg.n_entry = 1;
+ arg.max_n_entry = 1000;
+ arg.index = 0;
+ arg.total = 1;
+
+ length = smb_wcequiv_strlen(name);
+ if (ndr_rpc_server_os(domain_handle) == NATIVE_OS_WIN2000)
+ length += sizeof (smb_wchar_t);
+
+ arg.name.length = length;
+ arg.name.allosize = length;
+ arg.name.str = (unsigned char *)name;
+
+ if (ndr_rpc_call(domain_handle, opnum, &arg) != 0) {
+ status = NT_STATUS_INVALID_PARAMETER;
+ } else if (arg.status != NT_STATUS_SUCCESS) {
+ status = NT_SC_VALUE(arg.status);
+
+ /*
+ * Handle none-mapped status quietly.
+ */
+ if (status != NT_STATUS_NONE_MAPPED)
+ ndr_rpc_status(domain_handle, opnum, arg.status);
+ } else {
+ account->a_type = arg.rid_types.rid_type[0];
+ account->a_rid = arg.rids.rid[0];
+ status = NT_STATUS_SUCCESS;
+ }
+
+ ndr_rpc_release(domain_handle);
+ return (status);
+}
+
+/*
+ * samr_query_user_info
+ *
+ * Query information on a specific user. The handle must be a valid
+ * user handle obtained via samr_open_user.
+ *
+ * Returns 0 on success, otherwise returns -ve error code.
+ */
+int
+samr_query_user_info(mlsvc_handle_t *user_handle, WORD switch_value,
+ union samr_user_info *user_info)
+{
+ struct samr_QueryUserInfo arg;
+ int opnum;
+ int rc;
+
+ if (ndr_is_null_handle(user_handle) || user_info == 0)
+ return (-1);
+
+ opnum = SAMR_OPNUM_QueryUserInfo;
+ bzero(&arg, sizeof (struct samr_QueryUserInfo));
+
+ (void) memcpy(&arg.user_handle, &user_handle->handle,
+ sizeof (samr_handle_t));
+ arg.switch_value = switch_value;
+
+ if (ndr_rpc_call(user_handle, opnum, &arg) != 0) {
+ ndr_rpc_release(user_handle);
+ return (-1);
+ }
+
+ if (arg.status != 0)
+ rc = -1;
+ else
+ rc = samr_setup_user_info(switch_value, &arg, user_info);
+
+ ndr_rpc_release(user_handle);
+ return (rc);
+}
+
+/*
+ * samr_setup_user_info
+ *
+ * Private function to set up the samr_user_info data. Dependent on
+ * the switch value this function may use strdup which will malloc
+ * memory. The caller is responsible for deallocating this memory.
+ *
+ * Returns 0 on success, otherwise returns -1.
+ */
+static int
+samr_setup_user_info(WORD switch_value,
+ struct samr_QueryUserInfo *arg, union samr_user_info *user_info)
+{
+ struct samr_QueryUserInfo1 *info1;
+ struct samr_QueryUserInfo6 *info6;
+
+ switch (switch_value) {
+ case 1:
+ info1 = &arg->ru.info1;
+ user_info->info1.username = strdup(
+ (char const *)info1->username.str);
+ user_info->info1.fullname = strdup(
+ (char const *)info1->fullname.str);
+ user_info->info1.description = strdup(
+ (char const *)info1->description.str);
+ user_info->info1.unknown = 0;
+ user_info->info1.group_rid = info1->group_rid;
+ return (0);
+
+ case 6:
+ info6 = &arg->ru.info6;
+ user_info->info6.username = strdup(
+ (char const *)info6->username.str);
+ user_info->info6.fullname = strdup(
+ (char const *)info6->fullname.str);
+ return (0);
+
+ case 7:
+ user_info->info7.username = strdup(
+ (char const *)arg->ru.info7.username.str);
+ return (0);
+
+ case 8:
+ user_info->info8.fullname = strdup(
+ (char const *)arg->ru.info8.fullname.str);
+ return (0);
+
+ case 9:
+ user_info->info9.group_rid = arg->ru.info9.group_rid;
+ return (0);
+
+ case 16:
+ return (0);
+
+ default:
+ break;
+ };
+
+ return (-1);
+}
+
+/*
+ * samr_query_user_groups
+ *
+ * Query the groups for a specific user. The handle must be a valid
+ * user handle obtained via samr_open_user. The list of groups is
+ * returned in group_info. Note that group_info->groups is allocated
+ * using malloc. The caller is responsible for deallocating this
+ * memory when it is no longer required. If group_info->n_entry is 0
+ * then no memory was allocated.
+ *
+ * Returns 0 on success, otherwise returns -1.
+ */
+int
+samr_query_user_groups(mlsvc_handle_t *user_handle, int *n_groups,
+ struct samr_UserGroups **groups)
+{
+ struct samr_QueryUserGroups arg;
+ int opnum;
+ int rc;
+ int nbytes;
+
+ if (ndr_is_null_handle(user_handle))
+ return (-1);
+
+ opnum = SAMR_OPNUM_QueryUserGroups;
+ bzero(&arg, sizeof (struct samr_QueryUserGroups));
+
+ (void) memcpy(&arg.user_handle, &user_handle->handle,
+ sizeof (samr_handle_t));
+
+ rc = ndr_rpc_call(user_handle, opnum, &arg);
+ if (rc == 0) {
+ if (arg.info == 0) {
+ rc = -1;
+ } else {
+ nbytes = arg.info->n_entry *
+ sizeof (struct samr_UserGroups);
+
+ if ((*groups = malloc(nbytes)) == NULL) {
+ *n_groups = 0;
+ rc = -1;
+ } else {
+ *n_groups = arg.info->n_entry;
+ bcopy(arg.info->groups, *groups, nbytes);
+ }
+ }
+ }
+
+ ndr_rpc_release(user_handle);
+ return (rc);
+}
+
+/*
+ * samr_get_user_pwinfo
+ *
+ * Get some user password info. I'm not sure what this is yet but it is
+ * part of the create user sequence. The handle must be a valid user
+ * handle. Since I don't know what this is returning, I haven't provided
+ * any return data yet.
+ *
+ * Returns 0 on success. Otherwise returns an NT status code.
+ */
+DWORD
+samr_get_user_pwinfo(mlsvc_handle_t *user_handle)
+{
+ struct samr_GetUserPwInfo arg;
+ int opnum;
+ DWORD status;
+
+ if (ndr_is_null_handle(user_handle))
+ return (NT_STATUS_INVALID_PARAMETER);
+
+ opnum = SAMR_OPNUM_GetUserPwInfo;
+ bzero(&arg, sizeof (struct samr_GetUserPwInfo));
+ (void) memcpy(&arg.user_handle, &user_handle->handle,
+ sizeof (samr_handle_t));
+
+ if (ndr_rpc_call(user_handle, opnum, &arg) != 0) {
+ status = NT_STATUS_INVALID_PARAMETER;
+ } else if (arg.status != 0) {
+ ndr_rpc_status(user_handle, opnum, arg.status);
+ status = NT_SC_VALUE(arg.status);
+ } else {
+ status = 0;
+ }
+
+ ndr_rpc_release(user_handle);
+ return (status);
+}
+
+/*
+ * samr_set_user_info
+ *
+ * Returns 0 on success. Otherwise returns an NT status code.
+ * NT status codes observed so far:
+ * NT_STATUS_WRONG_PASSWORD
+ */
+/*ARGSUSED*/
+DWORD
+samr_set_user_info(mlsvc_handle_t *user_handle)
+{
+ unsigned char ssn_key[SMBAUTH_SESSION_KEY_SZ];
+ struct samr_SetUserInfo arg;
+ int opnum;
+ DWORD status = 0;
+
+ if (ndr_is_null_handle(user_handle))
+ return (NT_STATUS_INVALID_PARAMETER);
+
+ if (ndr_rpc_get_ssnkey(user_handle, ssn_key, sizeof (ssn_key)))
+ return (NT_STATUS_INVALID_PARAMETER);
+
+ opnum = SAMR_OPNUM_SetUserInfo;
+ bzero(&arg, sizeof (struct samr_SetUserInfo));
+ (void) memcpy(&arg.user_handle, &user_handle->handle,
+ sizeof (samr_handle_t));
+
+ arg.info.index = SAMR_SET_USER_INFO_23;
+ arg.info.switch_value = SAMR_SET_USER_INFO_23;
+
+ samr_set_user_unknowns(&arg.info.ru.info23);
+ samr_set_user_logon_hours(&arg);
+
+ if (samr_set_user_password(ssn_key, arg.info.ru.info23.password) < 0)
+ status = NT_STATUS_INTERNAL_ERROR;
+
+ if (ndr_rpc_call(user_handle, opnum, &arg) != 0) {
+ status = NT_STATUS_INVALID_PARAMETER;
+ } else if (arg.status != 0) {
+ ndr_rpc_status(user_handle, opnum, arg.status);
+ status = NT_SC_VALUE(arg.status);
+ }
+
+ ndr_rpc_release(user_handle);
+ return (status);
+}
+
+static void
+samr_set_user_unknowns(struct samr_SetUserInfo23 *info)
+{
+ bzero(info, sizeof (struct samr_SetUserInfo23));
+
+ info->sd.length = 0;
+ info->sd.data = 0;
+ info->user_rid = 0;
+ info->group_rid = DOMAIN_GROUP_RID_USERS;
+
+ /*
+ * The trust account value used here should probably
+ * match the one used to create the trust account.
+ */
+ info->acct_info = SAMR_AF_WORKSTATION_TRUST_ACCOUNT;
+ info->flags = 0x09F827FA;
+}
+
+/*
+ * samr_set_user_logon_hours
+ *
+ * SamrSetUserInfo appears to contain some logon hours information, which
+ * looks like a varying, conformant array. The top level contains a value
+ * (units), which probably indicates the how to interpret the array. The
+ * array definition looks like it contains a maximum size, an initial
+ * offset and a bit length (units/8), followed by the bitmap.
+ *
+ * (info)
+ * +-------+
+ * | units |
+ * +-------+ (hours)
+ * | hours |-->+-----------+
+ * +-------+ | max_is |
+ * +-----------+
+ * | first_is |
+ * +-----------+
+ * | length_is |
+ * +------------------------+
+ * | bitmap[length_is] |
+ * +---------+--------------+
+ *
+ * 10080 minutes/week => 10080/8 = 1260 (0x04EC) bytes.
+ * 168 hours/week => 168/8 = 21 (0xA8) bytes.
+ * In the netmon examples seen so far, all bits are set to 1, i.e.
+ * an array containing 0xff. This is probably the default setting.
+ *
+ * ndrgen has a problem with complex [size_is] statements (length/8).
+ * So, for now, we fake it using two separate components.
+ */
+static void
+samr_set_user_logon_hours(struct samr_SetUserInfo *sui)
+{
+ sui->logon_hours.size = SAMR_HOURS_MAX_SIZE;
+ sui->logon_hours.first = 0;
+ sui->logon_hours.length = SAMR_SET_USER_HOURS_SZ;
+ (void) memset(sui->logon_hours.bitmap, 0xFF, SAMR_SET_USER_HOURS_SZ);
+
+ sui->info.ru.info23.logon_info.units = SAMR_HOURS_PER_WEEK;
+ sui->info.ru.info23.logon_info.hours =
+ (DWORD)(uintptr_t)sui->logon_hours.bitmap;
+}
+
+/*
+ * samr_set_user_password
+ *
+ * Set the initial password for the user.
+ *
+ * Returns 0 if everything goes well, -1 if there is trouble generating a
+ * key.
+ */
+static int
+samr_set_user_password(unsigned char *nt_key, BYTE *oem_password)
+{
+ char hostname[NETBIOS_NAME_SZ];
+
+ randomize((char *)oem_password, SAMR_SET_USER_DATA_SZ);
+
+ /*
+ * The new password is going to be the NetBIOS name of the system
+ * in lower case.
+ */
+ if (smb_getnetbiosname(hostname, sizeof (hostname)) != 0)
+ return (-1);
+
+ (void) smb_strlwr(hostname);
+
+ /*
+ * Generate the OEM password from the hostname and the user session
+ * key(nt_key).
+ */
+ /*LINTED E_BAD_PTR_CAST_ALIGN*/
+ (void) sam_oem_password((oem_password_t *)oem_password,
+ (unsigned char *)hostname, nt_key);
+ return (0);
+}
diff --git a/usr/src/lib/smbsrv/libmlsvc/common/samr_lookup.c b/usr/src/lib/smbsrv/libmlsvc/common/samr_lookup.c
deleted file mode 100644
index 477a5a1e62..0000000000
--- a/usr/src/lib/smbsrv/libmlsvc/common/samr_lookup.c
+++ /dev/null
@@ -1,524 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-/*
- * Security Access Manager RPC (SAMR) library interface functions for
- * query and lookup calls.
- */
-
-
-#include <stdio.h>
-#include <strings.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include <smbsrv/libsmb.h>
-#include <smbsrv/libmlsvc.h>
-#include <smbsrv/ntstatus.h>
-#include <smbsrv/smb_sid.h>
-#include <samlib.h>
-#include <smbsrv/libmlrpc.h>
-
-static int samr_setup_user_info(WORD, struct samr_QueryUserInfo *,
- union samr_user_info *);
-static void samr_set_user_unknowns(struct samr_SetUserInfo23 *);
-static void samr_set_user_logon_hours(struct samr_SetUserInfo *);
-static int samr_set_user_password(unsigned char *, BYTE *);
-
-/*
- * samr_lookup_domain
- *
- * Lookup up the domain SID for the specified domain name. The handle
- * should be one returned from samr_connect. The allocated memory for
- * the returned SID must be freed by caller.
- */
-smb_sid_t *
-samr_lookup_domain(mlsvc_handle_t *samr_handle, char *domain_name)
-{
- struct samr_LookupDomain arg;
- smb_sid_t *domsid = NULL;
- int opnum;
- size_t length;
-
- if (ndr_is_null_handle(samr_handle) || domain_name == NULL)
- return (NULL);
-
- opnum = SAMR_OPNUM_LookupDomain;
- bzero(&arg, sizeof (struct samr_LookupDomain));
-
- (void) memcpy(&arg.handle, &samr_handle->handle,
- sizeof (samr_handle_t));
-
- length = smb_wcequiv_strlen(domain_name);
- if (ndr_rpc_server_os(samr_handle) == NATIVE_OS_WIN2000)
- length += sizeof (smb_wchar_t);
-
- arg.domain_name.length = length;
- arg.domain_name.allosize = length;
- arg.domain_name.str = (unsigned char *)domain_name;
-
- if (ndr_rpc_call(samr_handle, opnum, &arg) == 0)
- domsid = smb_sid_dup((smb_sid_t *)arg.sid);
-
- ndr_rpc_release(samr_handle);
- return (domsid);
-}
-
-/*
- * samr_enum_local_domains
- *
- * Get the list of local domains supported by a server.
- *
- * Returns NT status codes.
- */
-DWORD
-samr_enum_local_domains(mlsvc_handle_t *samr_handle)
-{
- struct samr_EnumLocalDomain arg;
- int opnum;
- DWORD status;
-
- if (ndr_is_null_handle(samr_handle))
- return (NT_STATUS_INVALID_PARAMETER);
-
- opnum = SAMR_OPNUM_EnumLocalDomains;
- bzero(&arg, sizeof (struct samr_EnumLocalDomain));
-
- (void) memcpy(&arg.handle, &samr_handle->handle,
- sizeof (samr_handle_t));
- arg.enum_context = 0;
- arg.max_length = 0x00002000; /* Value used by NT */
-
- if (ndr_rpc_call(samr_handle, opnum, &arg) != 0) {
- status = NT_STATUS_INVALID_PARAMETER;
- } else {
- status = NT_SC_VALUE(arg.status);
-
- /*
- * Handle none-mapped status quietly.
- */
- if (status != NT_STATUS_NONE_MAPPED)
- ndr_rpc_status(samr_handle, opnum, arg.status);
- }
-
- ndr_rpc_release(samr_handle);
- return (status);
-}
-
-/*
- * samr_lookup_domain_names
- *
- * Lookup up the given name in the domain specified by domain_handle.
- * Upon a successful lookup the information is returned in the account
- * arg and caller must free allocated memories by calling smb_account_free().
- *
- * Returns NT status codes.
- */
-uint32_t
-samr_lookup_domain_names(mlsvc_handle_t *domain_handle, char *name,
- smb_account_t *account)
-{
- struct samr_LookupNames arg;
- int opnum;
- uint32_t status;
- size_t length;
-
- if (ndr_is_null_handle(domain_handle) ||
- name == NULL || account == NULL) {
- return (NT_STATUS_INVALID_PARAMETER);
- }
-
- bzero(account, sizeof (smb_account_t));
- opnum = SAMR_OPNUM_LookupNames;
- bzero(&arg, sizeof (struct samr_LookupNames));
-
- (void) memcpy(&arg.handle, &domain_handle->handle,
- sizeof (samr_handle_t));
- arg.n_entry = 1;
- arg.max_n_entry = 1000;
- arg.index = 0;
- arg.total = 1;
-
- length = smb_wcequiv_strlen(name);
- if (ndr_rpc_server_os(domain_handle) == NATIVE_OS_WIN2000)
- length += sizeof (smb_wchar_t);
-
- arg.name.length = length;
- arg.name.allosize = length;
- arg.name.str = (unsigned char *)name;
-
- if (ndr_rpc_call(domain_handle, opnum, &arg) != 0) {
- status = NT_STATUS_INVALID_PARAMETER;
- } else if (arg.status != NT_STATUS_SUCCESS) {
- status = NT_SC_VALUE(arg.status);
-
- /*
- * Handle none-mapped status quietly.
- */
- if (status != NT_STATUS_NONE_MAPPED)
- ndr_rpc_status(domain_handle, opnum, arg.status);
- } else {
- account->a_type = arg.rid_types.rid_type[0];
- account->a_rid = arg.rids.rid[0];
- status = NT_STATUS_SUCCESS;
- }
-
- ndr_rpc_release(domain_handle);
- return (status);
-}
-
-/*
- * samr_query_user_info
- *
- * Query information on a specific user. The handle must be a valid
- * user handle obtained via samr_open_user.
- *
- * Returns 0 on success, otherwise returns -ve error code.
- */
-int
-samr_query_user_info(mlsvc_handle_t *user_handle, WORD switch_value,
- union samr_user_info *user_info)
-{
- struct samr_QueryUserInfo arg;
- int opnum;
- int rc;
-
- if (ndr_is_null_handle(user_handle) || user_info == 0)
- return (-1);
-
- opnum = SAMR_OPNUM_QueryUserInfo;
- bzero(&arg, sizeof (struct samr_QueryUserInfo));
-
- (void) memcpy(&arg.user_handle, &user_handle->handle,
- sizeof (samr_handle_t));
- arg.switch_value = switch_value;
-
- if (ndr_rpc_call(user_handle, opnum, &arg) != 0) {
- ndr_rpc_release(user_handle);
- return (-1);
- }
-
- if (arg.status != 0)
- rc = -1;
- else
- rc = samr_setup_user_info(switch_value, &arg, user_info);
-
- ndr_rpc_release(user_handle);
- return (rc);
-}
-
-/*
- * samr_setup_user_info
- *
- * Private function to set up the samr_user_info data. Dependent on
- * the switch value this function may use strdup which will malloc
- * memory. The caller is responsible for deallocating this memory.
- *
- * Returns 0 on success, otherwise returns -1.
- */
-static int
-samr_setup_user_info(WORD switch_value,
- struct samr_QueryUserInfo *arg, union samr_user_info *user_info)
-{
- struct samr_QueryUserInfo1 *info1;
- struct samr_QueryUserInfo6 *info6;
-
- switch (switch_value) {
- case 1:
- info1 = &arg->ru.info1;
- user_info->info1.username = strdup(
- (char const *)info1->username.str);
- user_info->info1.fullname = strdup(
- (char const *)info1->fullname.str);
- user_info->info1.description = strdup(
- (char const *)info1->description.str);
- user_info->info1.unknown = 0;
- user_info->info1.group_rid = info1->group_rid;
- return (0);
-
- case 6:
- info6 = &arg->ru.info6;
- user_info->info6.username = strdup(
- (char const *)info6->username.str);
- user_info->info6.fullname = strdup(
- (char const *)info6->fullname.str);
- return (0);
-
- case 7:
- user_info->info7.username = strdup(
- (char const *)arg->ru.info7.username.str);
- return (0);
-
- case 8:
- user_info->info8.fullname = strdup(
- (char const *)arg->ru.info8.fullname.str);
- return (0);
-
- case 9:
- user_info->info9.group_rid = arg->ru.info9.group_rid;
- return (0);
-
- case 16:
- return (0);
-
- default:
- break;
- };
-
- return (-1);
-}
-
-/*
- * samr_query_user_groups
- *
- * Query the groups for a specific user. The handle must be a valid
- * user handle obtained via samr_open_user. The list of groups is
- * returned in group_info. Note that group_info->groups is allocated
- * using malloc. The caller is responsible for deallocating this
- * memory when it is no longer required. If group_info->n_entry is 0
- * then no memory was allocated.
- *
- * Returns 0 on success, otherwise returns -1.
- */
-int
-samr_query_user_groups(mlsvc_handle_t *user_handle, int *n_groups,
- struct samr_UserGroups **groups)
-{
- struct samr_QueryUserGroups arg;
- int opnum;
- int rc;
- int nbytes;
-
- if (ndr_is_null_handle(user_handle))
- return (-1);
-
- opnum = SAMR_OPNUM_QueryUserGroups;
- bzero(&arg, sizeof (struct samr_QueryUserGroups));
-
- (void) memcpy(&arg.user_handle, &user_handle->handle,
- sizeof (samr_handle_t));
-
- rc = ndr_rpc_call(user_handle, opnum, &arg);
- if (rc == 0) {
- if (arg.info == 0) {
- rc = -1;
- } else {
- nbytes = arg.info->n_entry *
- sizeof (struct samr_UserGroups);
-
- if ((*groups = malloc(nbytes)) == NULL) {
- *n_groups = 0;
- rc = -1;
- } else {
- *n_groups = arg.info->n_entry;
- bcopy(arg.info->groups, *groups, nbytes);
- }
- }
- }
-
- ndr_rpc_release(user_handle);
- return (rc);
-}
-
-/*
- * samr_get_user_pwinfo
- *
- * Get some user password info. I'm not sure what this is yet but it is
- * part of the create user sequence. The handle must be a valid user
- * handle. Since I don't know what this is returning, I haven't provided
- * any return data yet.
- *
- * Returns 0 on success. Otherwise returns an NT status code.
- */
-DWORD
-samr_get_user_pwinfo(mlsvc_handle_t *user_handle)
-{
- struct samr_GetUserPwInfo arg;
- int opnum;
- DWORD status;
-
- if (ndr_is_null_handle(user_handle))
- return (NT_STATUS_INVALID_PARAMETER);
-
- opnum = SAMR_OPNUM_GetUserPwInfo;
- bzero(&arg, sizeof (struct samr_GetUserPwInfo));
- (void) memcpy(&arg.user_handle, &user_handle->handle,
- sizeof (samr_handle_t));
-
- if (ndr_rpc_call(user_handle, opnum, &arg) != 0) {
- status = NT_STATUS_INVALID_PARAMETER;
- } else if (arg.status != 0) {
- ndr_rpc_status(user_handle, opnum, arg.status);
- status = NT_SC_VALUE(arg.status);
- } else {
- status = 0;
- }
-
- ndr_rpc_release(user_handle);
- return (status);
-}
-
-/*
- * samr_set_user_info
- *
- * Returns 0 on success. Otherwise returns an NT status code.
- * NT status codes observed so far:
- * NT_STATUS_WRONG_PASSWORD
- */
-/*ARGSUSED*/
-DWORD
-samr_set_user_info(mlsvc_handle_t *user_handle)
-{
- unsigned char ssn_key[SMBAUTH_SESSION_KEY_SZ];
- struct samr_SetUserInfo arg;
- int opnum;
- DWORD status = 0;
-
- if (ndr_is_null_handle(user_handle))
- return (NT_STATUS_INVALID_PARAMETER);
-
- if (ndr_rpc_get_ssnkey(user_handle, ssn_key, sizeof (ssn_key)))
- return (NT_STATUS_INVALID_PARAMETER);
-
- opnum = SAMR_OPNUM_SetUserInfo;
- bzero(&arg, sizeof (struct samr_SetUserInfo));
- (void) memcpy(&arg.user_handle, &user_handle->handle,
- sizeof (samr_handle_t));
-
- arg.info.index = SAMR_SET_USER_INFO_23;
- arg.info.switch_value = SAMR_SET_USER_INFO_23;
-
- samr_set_user_unknowns(&arg.info.ru.info23);
- samr_set_user_logon_hours(&arg);
-
- if (samr_set_user_password(ssn_key, arg.info.ru.info23.password) < 0)
- status = NT_STATUS_INTERNAL_ERROR;
-
- if (ndr_rpc_call(user_handle, opnum, &arg) != 0) {
- status = NT_STATUS_INVALID_PARAMETER;
- } else if (arg.status != 0) {
- ndr_rpc_status(user_handle, opnum, arg.status);
- status = NT_SC_VALUE(arg.status);
- }
-
- ndr_rpc_release(user_handle);
- return (status);
-}
-
-static void
-samr_set_user_unknowns(struct samr_SetUserInfo23 *info)
-{
- bzero(info, sizeof (struct samr_SetUserInfo23));
-
- info->sd.length = 0;
- info->sd.data = 0;
- info->user_rid = 0;
- info->group_rid = DOMAIN_GROUP_RID_USERS;
-
- /*
- * The trust account value used here should probably
- * match the one used to create the trust account.
- */
- info->acct_info = SAMR_AF_WORKSTATION_TRUST_ACCOUNT;
- info->flags = 0x09F827FA;
-}
-
-/*
- * samr_set_user_logon_hours
- *
- * SamrSetUserInfo appears to contain some logon hours information, which
- * looks like a varying, conformant array. The top level contains a value
- * (units), which probably indicates the how to interpret the array. The
- * array definition looks like it contains a maximum size, an initial
- * offset and a bit length (units/8), followed by the bitmap.
- *
- * (info)
- * +-------+
- * | units |
- * +-------+ (hours)
- * | hours |-->+-----------+
- * +-------+ | max_is |
- * +-----------+
- * | first_is |
- * +-----------+
- * | length_is |
- * +------------------------+
- * | bitmap[length_is] |
- * +---------+--------------+
- *
- * 10080 minutes/week => 10080/8 = 1260 (0x04EC) bytes.
- * 168 hours/week => 168/8 = 21 (0xA8) bytes.
- * In the netmon examples seen so far, all bits are set to 1, i.e.
- * an array containing 0xff. This is probably the default setting.
- *
- * ndrgen has a problem with complex [size_is] statements (length/8).
- * So, for now, we fake it using two separate components.
- */
-static void
-samr_set_user_logon_hours(struct samr_SetUserInfo *sui)
-{
- sui->logon_hours.size = SAMR_HOURS_MAX_SIZE;
- sui->logon_hours.first = 0;
- sui->logon_hours.length = SAMR_SET_USER_HOURS_SZ;
- (void) memset(sui->logon_hours.bitmap, 0xFF, SAMR_SET_USER_HOURS_SZ);
-
- sui->info.ru.info23.logon_info.units = SAMR_HOURS_PER_WEEK;
- sui->info.ru.info23.logon_info.hours =
- (DWORD)(uintptr_t)sui->logon_hours.bitmap;
-}
-
-/*
- * samr_set_user_password
- *
- * Set the initial password for the user.
- *
- * Returns 0 if everything goes well, -1 if there is trouble generating a
- * key.
- */
-static int
-samr_set_user_password(unsigned char *nt_key, BYTE *oem_password)
-{
- char hostname[NETBIOS_NAME_SZ];
-
- randomize((char *)oem_password, SAMR_SET_USER_DATA_SZ);
-
- /*
- * The new password is going to be the NetBIOS name of the system
- * in lower case.
- */
- if (smb_getnetbiosname(hostname, sizeof (hostname)) != 0)
- return (-1);
-
- (void) smb_strlwr(hostname);
-
- /*
- * Generate the OEM password from the hostname and the user session
- * key(nt_key).
- */
- /*LINTED E_BAD_PTR_CAST_ALIGN*/
- (void) sam_oem_password((oem_password_t *)oem_password,
- (unsigned char *)hostname, nt_key);
- return (0);
-}
diff --git a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_sam.c b/usr/src/lib/smbsrv/libmlsvc/common/samr_svc.c
index a56214954e..d8a477ef6e 100644
--- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_sam.c
+++ b/usr/src/lib/smbsrv/libmlsvc/common/samr_svc.c
@@ -24,7 +24,13 @@
*/
/*
- * Security Accounts Manager RPC (SAMR) interface definition.
+ * Security Accounts Manager RPC (SAMR) server-side interface.
+ *
+ * The SAM is a hierarchical database:
+ * - If you want to talk to the SAM you need a SAM handle.
+ * - If you want to work with a domain, use the SAM handle.
+ * to obtain a domain handle.
+ * - Use domain handles to obtain user handles etc.
*/
#include <strings.h>
@@ -629,12 +635,7 @@ samr_s_OpenUser(void *arg, ndr_xa_t *mxa)
param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
} else {
bcopy(id, &param->user_handle, sizeof (samr_handle_t));
- /*
- * Need QueryUserInfo(level 21).
- */
- samr_hdfree(mxa, id);
- bzero(&param->user_handle, sizeof (samr_handle_t));
- param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
+ param->status = NT_STATUS_SUCCESS;
}
return (NDR_DRC_OK);
@@ -660,8 +661,6 @@ samr_s_DeleteUser(void *arg, ndr_xa_t *mxa)
/*
* samr_s_QueryUserInfo
*
- * The caller should provide a valid user key.
- *
* Returns:
* NT_STATUS_SUCCESS
* NT_STATUS_ACCESS_DENIED
@@ -671,10 +670,72 @@ samr_s_DeleteUser(void *arg, ndr_xa_t *mxa)
static int
samr_s_QueryUserInfo(void *arg, ndr_xa_t *mxa)
{
- struct samr_QueryUserInfo *param = arg;
+ static uint16_t owf_buf[8];
+ static uint8_t hour_buf[SAMR_SET_USER_HOURS_SZ];
+ struct samr_QueryUserInfo *param = arg;
+ struct samr_QueryUserInfo21 *all_info;
+ ndr_hdid_t *id;
+ ndr_handle_t *hd;
+ samr_keydata_t *data;
+ smb_domain_t di;
+ smb_account_t account;
+ smb_sid_t *sid;
+ uint32_t status;
+
+ id = (ndr_hdid_t *)&param->user_handle;
+ if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_USER)) == NULL) {
+ status = NT_STATUS_INVALID_HANDLE;
+ goto QueryUserInfoError;
+ }
+
+ data = (samr_keydata_t *)hd->nh_data;
+
+ if (param->switch_value != SAMR_QUERY_USER_ALL_INFO) {
+ status = NT_STATUS_ACCESS_DENIED;
+ goto QueryUserInfoError;
+ }
+ if (!smb_domain_lookup_type(SMB_DOMAIN_LOCAL, &di)) {
+ status = NT_STATUS_ACCESS_DENIED;
+ goto QueryUserInfoError;
+ }
+
+ if ((sid = smb_sid_splice(di.di_binsid, data->kd_rid)) == NULL) {
+ status = NT_STATUS_ACCESS_DENIED;
+ goto QueryUserInfoError;
+ }
+
+ if (smb_sam_lookup_sid(sid, &account) != NT_STATUS_SUCCESS) {
+ status = NT_STATUS_ACCESS_DENIED;
+ goto QueryUserInfoError;
+ }
+
+ all_info = &param->ru.info21;
+ bzero(all_info, sizeof (struct samr_QueryUserInfo21));
+
+ all_info->WhichFields = SAMR_USER_ALL_USERNAME | SAMR_USER_ALL_USERID;
+
+ (void) NDR_MSTRING(mxa, account.a_name,
+ (ndr_mstring_t *)&all_info->UserName);
+ all_info->UserId = data->kd_rid;
+
+ all_info->LmOwfPassword.length = 16;
+ all_info->LmOwfPassword.maxlen = 16;
+ all_info->LmOwfPassword.buf = owf_buf;
+ all_info->NtOwfPassword.length = 16;
+ all_info->NtOwfPassword.maxlen = 16;
+ all_info->NtOwfPassword.buf = owf_buf;
+ all_info->LogonHours.units_per_week = SAMR_HOURS_PER_WEEK;
+ all_info->LogonHours.hours = hour_buf;
+
+ param->address = 1;
+ param->switch_index = SAMR_QUERY_USER_ALL_INFO;
+ param->status = NT_STATUS_SUCCESS;
+ return (NDR_DRC_OK);
+
+QueryUserInfoError:
bzero(param, sizeof (struct samr_QueryUserInfo));
- param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
+ param->status = NT_SC_ERROR(status);
return (NDR_DRC_OK);
}
@@ -1567,6 +1628,7 @@ fixup_samr_QueryUserInfo(struct samr_QueryUserInfo *val)
CASE_INFO_ENT(samr_QueryUserInfo, 8);
CASE_INFO_ENT(samr_QueryUserInfo, 9);
CASE_INFO_ENT(samr_QueryUserInfo, 16);
+ CASE_INFO_ENT(samr_QueryUserInfo, 21);
default:
return;
diff --git a/usr/src/lib/smbsrv/libmlsvc/common/smb_autohome.c b/usr/src/lib/smbsrv/libmlsvc/common/smb_autohome.c
index 695bfb55b7..ba6f81c3fb 100644
--- a/usr/src/lib/smbsrv/libmlsvc/common/smb_autohome.c
+++ b/usr/src/lib/smbsrv/libmlsvc/common/smb_autohome.c
@@ -68,10 +68,11 @@ static void smb_autohome_parse_options(smb_share_t *);
* autohome shares.
*/
void
-smb_autohome_add(const char *username)
+smb_autohome_add(const smb_token_t *token)
{
- smb_share_t si;
- smb_autohome_t *ai;
+ smb_share_t si;
+ smb_autohome_t *ai;
+ char *username = token->tkn_account_name;
assert(username);
@@ -98,8 +99,11 @@ smb_autohome_add(const char *username)
(void) strlcpy(si.shr_name, username, MAXNAMELEN);
(void) strlcpy(si.shr_container, ai->ah_container, MAXPATHLEN);
+ (void) strlcpy(si.shr_cmnt, "Autohome", SMB_SHARE_CMNT_MAX);
smb_autohome_parse_options(&si);
si.shr_flags |= SMB_SHRF_TRANS | SMB_SHRF_AUTOHOME;
+ si.shr_uid = token->tkn_user.i_id;
+ si.shr_gid = token->tkn_primary_grp.i_id;
(void) smb_shr_add(&si);
}
diff --git a/usr/src/lib/smbsrv/libmlsvc/common/smb_logon.c b/usr/src/lib/smbsrv/libmlsvc/common/smb_logon.c
index 5b78165a68..d626a443f4 100644
--- a/usr/src/lib/smbsrv/libmlsvc/common/smb_logon.c
+++ b/usr/src/lib/smbsrv/libmlsvc/common/smb_logon.c
@@ -434,7 +434,8 @@ smb_logon(netr_client_t *clnt)
status = smb_logon_anon(clnt, token);
if (status == NT_STATUS_INVALID_LOGON_TYPE) {
status = smb_logon_local(clnt, token);
- if (status != NT_STATUS_SUCCESS) {
+ if ((status != NT_STATUS_SUCCESS) &&
+ (smb_config_get_secmode() == SMB_SECMODE_DOMAIN)) {
if ((status == NT_STATUS_INVALID_LOGON_TYPE) ||
(*clnt->e_domain == '\0'))
status = smb_logon_domain(clnt, token);
diff --git a/usr/src/lib/smbsrv/libmlsvc/common/smb_share.c b/usr/src/lib/smbsrv/libmlsvc/common/smb_share.c
index d42622dfca..0c8f4b296b 100644
--- a/usr/src/lib/smbsrv/libmlsvc/common/smb_share.c
+++ b/usr/src/lib/smbsrv/libmlsvc/common/smb_share.c
@@ -384,7 +384,7 @@ smb_shr_add(smb_share_t *si)
assert(si != NULL);
- if (!smb_shr_chkname(si->shr_name))
+ if (smb_name_validate_share(si->shr_name) != ERROR_SUCCESS)
return (ERROR_INVALID_NAME);
if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) != NERR_Success)
@@ -450,7 +450,7 @@ smb_shr_remove(char *sharename)
assert(sharename != NULL);
- if (!smb_shr_chkname(sharename))
+ if (smb_name_validate_share(sharename) != ERROR_SUCCESS)
return (ERROR_INVALID_NAME);
if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) != NERR_Success)
@@ -507,7 +507,8 @@ smb_shr_rename(char *from_name, char *to_name)
assert((from_name != NULL) && (to_name != NULL));
- if (!smb_shr_chkname(from_name) || !smb_shr_chkname(to_name))
+ if (smb_name_validate_share(from_name) != ERROR_SUCCESS ||
+ smb_name_validate_share(to_name) != ERROR_SUCCESS)
return (ERROR_INVALID_NAME);
if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) != NERR_Success)
@@ -830,34 +831,6 @@ smb_shr_is_admin(char *sharename)
}
/*
- * smb_shr_chkname
- *
- * Check for invalid characters in a share name. The list of invalid
- * characters includes control characters and the following:
- *
- * " / \ [ ] : | < > + ; , ? * =
- */
-boolean_t
-smb_shr_chkname(char *sharename)
-{
- char *invalid = "\"/\\[]:|<>+;,?*=";
- char *cp;
-
- if (sharename == NULL)
- return (B_FALSE);
-
- if (strpbrk(sharename, invalid))
- return (B_FALSE);
-
- for (cp = sharename; *cp != '\0'; cp++) {
- if (iscntrl(*cp))
- return (B_FALSE);
- }
-
- return (B_TRUE);
-}
-
-/*
* smb_shr_get_realpath
*
* Derive the real path for a share from the path provided by a client.
diff --git a/usr/src/lib/smbsrv/libmlsvc/common/srvsvc_sd.c b/usr/src/lib/smbsrv/libmlsvc/common/srvsvc_sd.c
index a5a3aad694..4b92b5dc58 100644
--- a/usr/src/lib/smbsrv/libmlsvc/common/srvsvc_sd.c
+++ b/usr/src/lib/smbsrv/libmlsvc/common/srvsvc_sd.c
@@ -40,6 +40,7 @@
#define SRVSVC_ACE_OFFSET 8
#define SRVSVC_SID_OFFSET 8
+static uint32_t srvsvc_sd_get_autohome(const smb_share_t *, smb_sd_t *);
static uint32_t srvsvc_sd_status_to_error(uint32_t);
static uint32_t srvsvc_sd_set_relative(smb_sd_t *, uint8_t *);
static uint32_t srvsvc_sd_set_absolute(uint8_t *, smb_sd_t *);
@@ -151,13 +152,19 @@ srvsvc_sd_get(smb_share_t *si, uint8_t *sdbuf, uint32_t *size)
if (sdbuf == NULL && size == NULL)
return (ERROR_INVALID_PARAMETER);
- ret = srvsvc_shareacl_getpath(si, path);
- if (ret != 0)
- return (ERROR_PATH_NOT_FOUND);
-
bzero(&sd, sizeof (smb_sd_t));
- status = smb_sd_read(path, &sd, SMB_ALL_SECINFO);
- status = srvsvc_sd_status_to_error(status);
+
+ if (si->shr_flags & SMB_SHRF_AUTOHOME) {
+ status = srvsvc_sd_get_autohome(si, &sd);
+ } else {
+ ret = srvsvc_shareacl_getpath(si, path);
+ if (ret != 0)
+ return (ERROR_PATH_NOT_FOUND);
+
+ status = smb_sd_read(path, &sd, SMB_ALL_SECINFO);
+ status = srvsvc_sd_status_to_error(status);
+ }
+
if (status != ERROR_SUCCESS) {
smb_sd_term(&sd);
return (status);
@@ -175,6 +182,28 @@ srvsvc_sd_get(smb_share_t *si, uint8_t *sdbuf, uint32_t *size)
return (status);
}
+static uint32_t
+srvsvc_sd_get_autohome(const smb_share_t *si, smb_sd_t *sd)
+{
+ smb_fssd_t fs_sd;
+ acl_t *acl;
+ uint32_t status;
+
+ if (acl_fromtext("owner@:rwxpdDaARWcCos::allow", &acl) != 0)
+ return (ERROR_NOT_ENOUGH_MEMORY);
+
+ smb_fssd_init(&fs_sd, SMB_ALL_SECINFO, SMB_FSSD_FLAGS_DIR);
+ fs_sd.sd_uid = si->shr_uid;
+ fs_sd.sd_gid = si->shr_gid;
+ fs_sd.sd_zdacl = acl;
+ fs_sd.sd_zsacl = NULL;
+
+ status = smb_sd_fromfs(&fs_sd, sd);
+ status = srvsvc_sd_status_to_error(status);
+ smb_fssd_term(&fs_sd);
+ return (status);
+}
+
/*
* This method converts an ACE from absolute (pointer) to
* self relative (flat buffer) format.
diff --git a/usr/src/lib/smbsrv/libmlsvc/common/srvsvc_svc.c b/usr/src/lib/smbsrv/libmlsvc/common/srvsvc_svc.c
index 08eeca4462..d829d4335f 100644
--- a/usr/src/lib/smbsrv/libmlsvc/common/srvsvc_svc.c
+++ b/usr/src/lib/smbsrv/libmlsvc/common/srvsvc_svc.c
@@ -57,8 +57,6 @@
#include <smbsrv/smb_common_door.h>
#include "mlsvc.h"
-#define SV_TYPE_SENT_BY_ME (SV_TYPE_WORKSTATION | SV_TYPE_SERVER | SV_TYPE_NT)
-
/*
* Qualifier types for NetConnectEnum.
*/
@@ -1678,7 +1676,7 @@ netservergetinfo_no_memory:
info101->sv101_platform_id = SV_PLATFORM_ID_NT;
info101->sv101_version_major = 4;
info101->sv101_version_minor = 0;
- info101->sv101_type = SV_TYPE_SENT_BY_ME;
+ info101->sv101_type = SV_TYPE_DEFAULT;
info101->sv101_name = (uint8_t *)NDR_STRDUP(mxa, hostname);
info101->sv101_comment
= (uint8_t *)NDR_STRDUP(mxa, sys_comment);
@@ -1699,7 +1697,7 @@ netservergetinfo_no_memory:
info102->sv102_platform_id = SV_PLATFORM_ID_NT;
info102->sv102_version_major = 4;
info102->sv102_version_minor = 0;
- info102->sv102_type = SV_TYPE_SENT_BY_ME;
+ info102->sv102_type = SV_TYPE_DEFAULT;
info102->sv102_name = (uint8_t *)NDR_STRDUP(mxa, hostname);
info102->sv102_comment
= (uint8_t *)NDR_STRDUP(mxa, sys_comment);
@@ -1843,11 +1841,6 @@ srvsvc_s_NetRemoteTOD(void *arg, ndr_xa_t *mxa)
*
* Perform name validation.
*
- * The share name is considered invalid if it contains any of the
- * following character (MSDN 236388).
- *
- * " / \ [ ] : | < > + ; , ? * =
- *
* Returns Win32 error codes.
*/
/*ARGSUSED*/
@@ -1856,6 +1849,7 @@ srvsvc_s_NetNameValidate(void *arg, ndr_xa_t *mxa)
{
struct mslm_NetNameValidate *param = arg;
char *name;
+ int maxlen;
int len;
if ((name = (char *)param->pathname) == NULL) {
@@ -1863,34 +1857,41 @@ srvsvc_s_NetNameValidate(void *arg, ndr_xa_t *mxa)
return (NDR_DRC_OK);
}
- len = strlen(name);
-
- if ((param->flags == 0 && len > 81) ||
- (param->flags == 0x80000000 && len > 13)) {
- param->status = ERROR_INVALID_NAME;
- return (NDR_DRC_OK);
- }
-
switch (param->type) {
case NAMETYPE_SHARE:
- if (smb_shr_chkname(name))
- param->status = ERROR_SUCCESS;
- else
+ len = strlen(name);
+ maxlen = (param->flags & NAMEFLAG_LM2) ?
+ SMB_SHARE_OEMNAME_MAX : SMB_SHARE_NTNAME_MAX;
+
+ if (len > maxlen) {
param->status = ERROR_INVALID_NAME;
+ return (NDR_DRC_OK);
+ }
+
+ param->status = smb_name_validate_share(name);
break;
case NAMETYPE_USER:
- case NAMETYPE_PASSWORD:
case NAMETYPE_GROUP:
+ param->status = smb_name_validate_account(name);
+ break;
+
+ case NAMETYPE_DOMAIN: /* NetBIOS domain name */
+ param->status = smb_name_validate_nbdomain(name);
+ break;
+
+ case NAMETYPE_WORKGROUP:
+ param->status = smb_name_validate_workgroup(name);
+ break;
+
+ case NAMETYPE_PASSWORD:
case NAMETYPE_COMPUTER:
case NAMETYPE_EVENT:
- case NAMETYPE_DOMAIN:
case NAMETYPE_SERVICE:
case NAMETYPE_NET:
case NAMETYPE_MESSAGE:
case NAMETYPE_MESSAGEDEST:
case NAMETYPE_SHAREPASSWORD:
- case NAMETYPE_WORKGROUP:
param->status = ERROR_NOT_SUPPORTED;
break;
diff --git a/usr/src/lib/smbsrv/libsmb/common/libsmb.h b/usr/src/lib/smbsrv/libsmb/common/libsmb.h
index 189bce0021..f9acbec34c 100644
--- a/usr/src/lib/smbsrv/libsmb/common/libsmb.h
+++ b/usr/src/lib/smbsrv/libsmb/common/libsmb.h
@@ -47,6 +47,7 @@ extern "C" {
#include <smbsrv/smb_idmap.h>
#include <smbsrv/netbios.h>
#include <smbsrv/smb_share.h>
+#include <smbsrv/nterror.h>
#include <smbsrv/ntstatus.h>
#include <smbsrv/smb_door_svc.h>
#include <smbsrv/alloc.h>
@@ -697,8 +698,8 @@ int smb_lgrp_iteropen(smb_giter_t *);
void smb_lgrp_iterclose(smb_giter_t *);
int smb_lgrp_iterate(smb_giter_t *, smb_group_t *);
-int smb_lookup_sid(smb_sid_t *, char *buf, int buflen);
-int smb_lookup_name(char *, smb_gsid_t *);
+int smb_lookup_sid(const char *, lsa_account_t *);
+int smb_lookup_name(const char *, sid_type_t, lsa_account_t *);
#define SMB_LGRP_SUCCESS 0
#define SMB_LGRP_INVALID_ARG 1
@@ -733,9 +734,7 @@ int smb_lookup_name(char *, smb_gsid_t *);
#define SMB_LGRP_LOOKUP_FAILED 30
#define SMB_LGRP_NOT_SUPPORTED 31
-#define SMB_LGRP_NAME_CHAR_MAX 32
#define SMB_LGRP_COMMENT_MAX 256
-#define SMB_LGRP_NAME_MAX (SMB_LGRP_NAME_CHAR_MAX * MTS_MB_CHAR_MAX + 1)
/*
* values for smb_nic_t.smbflags
@@ -847,6 +846,7 @@ boolean_t smb_account_validate(smb_account_t *);
*/
uint32_t smb_sd_read(char *path, smb_sd_t *, uint32_t);
uint32_t smb_sd_write(char *path, smb_sd_t *, uint32_t);
+uint32_t smb_sd_fromfs(smb_fssd_t *, smb_sd_t *);
/* Kernel Module Interface */
int smb_kmod_bind(void);
@@ -867,6 +867,13 @@ void smb_kmod_enum_fini(smb_netsvc_t *);
int smb_kmod_session_close(const char *, const char *);
int smb_kmod_file_close(uint32_t);
+void smb_name_parse(char *, char **, char **);
+uint32_t smb_name_validate_share(const char *);
+uint32_t smb_name_validate_account(const char *);
+uint32_t smb_name_validate_domain(const char *);
+uint32_t smb_name_validate_nbdomain(const char *);
+uint32_t smb_name_validate_workgroup(const char *);
+
/*
* Interposer library validation
*/
diff --git a/usr/src/lib/smbsrv/libsmb/common/mapfile-vers b/usr/src/lib/smbsrv/libsmb/common/mapfile-vers
index 4191970939..43e39c72da 100644
--- a/usr/src/lib/smbsrv/libsmb/common/mapfile-vers
+++ b/usr/src/lib/smbsrv/libsmb/common/mapfile-vers
@@ -70,6 +70,7 @@ SUNWprivate {
list_prev;
list_remove;
list_tail;
+ lsa_account_xdr;
netr_client_mkabsolute;
netr_client_xfree;
oemtoucs;
@@ -280,6 +281,12 @@ SUNWprivate {
smb_msgbuf_term;
smb_msgbuf_used;
smb_msgbuf_word_align;
+ smb_name_parse;
+ smb_name_validate_account;
+ smb_name_validate_share;
+ smb_name_validate_domain;
+ smb_name_validate_nbdomain;
+ smb_name_validate_workgroup;
smb_netconnectinfo_decode;
smb_netconnectinfo_encode;
smb_netfileinfo_decode;
@@ -330,6 +337,7 @@ SUNWprivate {
smb_sam_usr_groups;
smb_sbequiv_strlen;
smb_sd_get_secinfo;
+ smb_sd_fromfs;
smb_sd_init;
smb_sd_len;
smb_sd_term;
@@ -348,6 +356,7 @@ SUNWprivate {
smb_sid_len;
smb_sid_splice;
smb_sid_split;
+ smb_sid_splitstr;
smb_sid_tostr;
smb_sid_type2str;
smb_smf_maintenance_mode;
diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_api_door_calls.c b/usr/src/lib/smbsrv/libsmb/common/smb_api_door_calls.c
index 417bc55896..e6fb3fe6ca 100644
--- a/usr/src/lib/smbsrv/libsmb/common/smb_api_door_calls.c
+++ b/usr/src/lib/smbsrv/libsmb/common/smb_api_door_calls.c
@@ -41,121 +41,110 @@
#include <smbsrv/smb_common_door.h>
/*
- * smb_lookup_sid
+ * Given a SID, make a door call to get the associated name.
*
- * Tries to get the account name associated with the given SID
- * The mapping is requested to be performed by smbd via a door
- * call. If no account name can be found the string format of
- * the SID will be returned as the name.
+ * Returns 0 if the door call is successful, otherwise -1.
*
- * The passed namebuf should be big enough to hold the string
- * format of a SID.
+ * If 0 is returned, the lookup result will be available in a_status.
+ * NT_STATUS_SUCCESS The SID was mapped to a name.
+ * NT_STATUS_NONE_MAPPED The SID could not be mapped to a name.
*/
int
-smb_lookup_sid(smb_sid_t *sid, char *namebuf, int namebuflen)
+smb_lookup_sid(const char *sid, lsa_account_t *acct)
{
- door_arg_t arg;
- char *buf;
- size_t len;
- int opcode = SMB_DR_LOOKUP_SID;
- char *name = NULL;
- int fd;
+ door_arg_t arg;
+ char *buf;
+ size_t len;
+ int opcode = SMB_DR_LOOKUP_SID;
+ int fd;
+ int rc;
- assert((namebuf != NULL) && (namebuflen != 0));
+ assert((sid != NULL) && (acct != NULL));
- if (!smb_sid_isvalid(sid))
- return (NT_STATUS_INVALID_SID);
+ bzero(acct, sizeof (lsa_account_t));
+ (void) strlcpy(acct->a_sid, sid, SMB_SID_STRSZ);
- smb_sid_tostr(sid, namebuf);
-
- if ((fd = open(SMB_DR_SVC_NAME, O_RDONLY)) < 0) {
- /* returning string SID */
- return (NT_STATUS_SUCCESS);
- }
+ if ((fd = open(SMB_DR_SVC_NAME, O_RDONLY)) < 0)
+ return (-1);
- if ((buf = smb_dr_encode_string(opcode, namebuf, &len)) == 0) {
- /* returning string SID */
+ buf = smb_dr_encode_common(opcode, acct, lsa_account_xdr, &len);
+ if (buf == NULL) {
(void) close(fd);
- return (NT_STATUS_SUCCESS);
+ return (-1);
}
smb_dr_clnt_setup(&arg, buf, len);
- if (smb_dr_clnt_call(fd, &arg) == 0) {
+ if ((rc = smb_dr_clnt_call(fd, &arg)) == 0) {
buf = arg.rbuf + SMB_DR_DATA_OFFSET;
len = arg.rsize - SMB_DR_DATA_OFFSET;
- name = smb_dr_decode_string(buf, len);
+
+ rc = smb_dr_decode_common(buf, len, lsa_account_xdr, acct);
}
smb_dr_clnt_cleanup(&arg);
(void) close(fd);
-
- if (name) {
- if (*name != '\0')
- (void) strlcpy(namebuf, name, namebuflen);
-
- xdr_free(xdr_string, (char *)&name);
- }
-
- return (NT_STATUS_SUCCESS);
+ return (rc);
}
/*
- * smb_lookup_name
+ * Given a name, make a door call to get the associated SID.
*
- * Tries to get the SID associated with the given account name
- * The mapping is requested to be performed by smbd via a door
- * call. If no SID can be found NT_STATUS_NONE_MAPPED is returned.
+ * Returns 0 if the door call is successful, otherwise -1.
+ *
+ * If 0 is returned, the lookup result will be available in a_status.
+ * NT_STATUS_SUCCESS The name was mapped to a SID.
+ * NT_STATUS_NONE_MAPPED The name could not be mapped to a SID.
*/
int
-smb_lookup_name(char *name, smb_gsid_t *sid)
+smb_lookup_name(const char *name, sid_type_t sidtype, lsa_account_t *acct)
{
- door_arg_t arg;
- char *buf;
- size_t len;
- int opcode = SMB_DR_LOOKUP_NAME;
- char *strsid = NULL;
- char *p;
- int fd;
-
- assert(name && sid);
-
- if (*name == '\0')
- return (NT_STATUS_NONE_MAPPED);
+ char tmp[MAXNAMELEN];
+ door_arg_t arg;
+ char *buf;
+ char *dp = NULL;
+ char *np = NULL;
+ size_t len;
+ int opcode = SMB_DR_LOOKUP_NAME;
+ int fd;
+ int rc;
+
+ assert((name != NULL) && (acct != NULL));
+
+ (void) strlcpy(tmp, name, MAXNAMELEN);
+ smb_name_parse(tmp, &np, &dp);
+
+ bzero(acct, sizeof (lsa_account_t));
+ acct->a_sidtype = sidtype;
+
+ if (dp != NULL && np != NULL) {
+ (void) strlcpy(acct->a_domain, dp, MAXNAMELEN);
+ (void) strlcpy(acct->a_name, np, MAXNAMELEN);
+ } else {
+ (void) strlcpy(acct->a_name, name, MAXNAMELEN);
+ }
if ((fd = open(SMB_DR_SVC_NAME, O_RDONLY)) < 0)
- return (NT_STATUS_INTERNAL_ERROR);
+ return (-1);
- if ((buf = smb_dr_encode_string(opcode, name, &len)) == 0) {
+ buf = smb_dr_encode_common(opcode, acct, lsa_account_xdr, &len);
+ if (buf == NULL) {
(void) close(fd);
- return (NT_STATUS_INTERNAL_ERROR);
+ return (-1);
}
smb_dr_clnt_setup(&arg, buf, len);
- if (smb_dr_clnt_call(fd, &arg) == 0) {
+ if ((rc = smb_dr_clnt_call(fd, &arg)) == 0) {
buf = arg.rbuf + SMB_DR_DATA_OFFSET;
len = arg.rsize - SMB_DR_DATA_OFFSET;
- strsid = smb_dr_decode_string(buf, len);
+
+ rc = smb_dr_decode_common(buf, len, lsa_account_xdr, acct);
}
smb_dr_clnt_cleanup(&arg);
(void) close(fd);
-
- if (strsid == NULL)
- return (NT_STATUS_INTERNAL_ERROR);
-
- p = strchr(strsid, '-');
- if (p == NULL) {
- xdr_free(xdr_string, (char *)&strsid);
- return (NT_STATUS_NONE_MAPPED);
- }
-
- *p++ = '\0';
- sid->gs_type = atoi(strsid);
- sid->gs_sid = smb_sid_fromstr(p);
- xdr_free(xdr_string, (char *)&strsid);
- return (NT_STATUS_SUCCESS);
+ return (rc);
}
uint32_t
diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_door_encdec.c b/usr/src/lib/smbsrv/libsmb/common/smb_door_encdec.c
index bce2ad677b..b746060c99 100644
--- a/usr/src/lib/smbsrv/libsmb/common/smb_door_encdec.c
+++ b/usr/src/lib/smbsrv/libsmb/common/smb_door_encdec.c
@@ -266,3 +266,59 @@ smb_dr_decode_arg_get_token(char *buf, size_t len)
xdr_free(xdr_smb_dr_bytes_t, (char *)&arg);
return (clnt_info);
}
+
+/*
+ * Encode an lsa_account_t into a buffer.
+ */
+int
+lsa_account_encode(lsa_account_t *acct, uint8_t *buf, uint32_t buflen)
+{
+ XDR xdrs;
+ int rc = 0;
+
+ xdrmem_create(&xdrs, (const caddr_t)buf, buflen, XDR_ENCODE);
+
+ if (!lsa_account_xdr(&xdrs, acct))
+ rc = -1;
+
+ xdr_destroy(&xdrs);
+ return (rc);
+}
+
+/*
+ * Decode an XDR buffer into an lsa_account_t.
+ */
+int
+lsa_account_decode(lsa_account_t *acct, uint8_t *buf, uint32_t buflen)
+{
+ XDR xdrs;
+ int rc = 0;
+
+ xdrmem_create(&xdrs, (const caddr_t)buf, buflen, XDR_DECODE);
+
+ bzero(acct, sizeof (lsa_account_t));
+ if (!lsa_account_xdr(&xdrs, acct))
+ rc = -1;
+
+ xdr_destroy(&xdrs);
+ return (rc);
+}
+
+bool_t
+lsa_account_xdr(XDR *xdrs, lsa_account_t *objp)
+{
+ if (!xdr_uint16_t(xdrs, &objp->a_sidtype))
+ return (FALSE);
+ if (!xdr_uint32_t(xdrs, &objp->a_status))
+ return (FALSE);
+ if (!xdr_vector(xdrs, (char *)objp->a_domain, MAXNAMELEN,
+ sizeof (char), (xdrproc_t)xdr_char))
+ return (FALSE);
+ if (!xdr_vector(xdrs, (char *)objp->a_name, MAXNAMELEN,
+ sizeof (char), (xdrproc_t)xdr_char))
+ return (FALSE);
+ if (!xdr_vector(xdrs, (char *)objp->a_sid, SMB_SID_STRSZ,
+ sizeof (char), (xdrproc_t)xdr_char))
+ return (FALSE);
+ return (TRUE);
+}
diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_lgrp.c b/usr/src/lib/smbsrv/libsmb/common/smb_lgrp.c
index d8bc1d69fe..f5c82001bc 100644
--- a/usr/src/lib/smbsrv/libsmb/common/smb_lgrp.c
+++ b/usr/src/lib/smbsrv/libsmb/common/smb_lgrp.c
@@ -23,8 +23,6 @@
* Use is subject to license terms.
*/
-#pragma ident "@(#)smb_lgrp.c 1.5 08/07/29 SMI"
-
#include <stdlib.h>
#include <strings.h>
#include <unistd.h>
@@ -178,7 +176,7 @@ static int smb_lgrp_decode_privset(smb_group_t *, char *, char *);
static int smb_lgrp_decode_members(smb_group_t *, char *, char *, sqlite *);
static void smb_lgrp_set_default_privs(smb_group_t *);
-static boolean_t smb_lgrp_chkname(char *);
+static boolean_t smb_lgrp_normalize_name(char *);
static boolean_t smb_lgrp_chkmember(uint16_t);
static int smb_lgrp_getsid(int, uint32_t *, uint16_t, sqlite *, smb_sid_t **);
static int smb_lgrp_getgid(uint32_t rid, gid_t *gid);
@@ -206,8 +204,7 @@ smb_lgrp_add(char *gname, char *cmnt)
sqlite *db;
int rc;
- (void) trim_whitespace(gname);
- if (!smb_lgrp_chkname(gname))
+ if (!smb_lgrp_normalize_name(gname))
return (SMB_LGRP_INVALID_NAME);
if (cmnt && (strlen(cmnt) > SMB_LGRP_COMMENT_MAX))
@@ -278,12 +275,10 @@ smb_lgrp_rename(char *gname, char *new_gname)
sqlite *db;
int rc;
- (void) trim_whitespace(gname);
- if (!smb_lgrp_chkname(gname))
+ if (!smb_lgrp_normalize_name(gname))
return (SMB_LGRP_INVALID_NAME);
- (void) trim_whitespace(new_gname);
- if (!smb_lgrp_chkname(gname))
+ if (!smb_lgrp_normalize_name(gname))
return (SMB_LGRP_INVALID_NAME);
if (smb_strcasecmp(gname, new_gname, 0) == 0)
@@ -317,8 +312,7 @@ smb_lgrp_delete(char *gname)
sqlite *db;
int rc;
- (void) trim_whitespace(gname);
- if (!smb_lgrp_chkname(gname))
+ if (!smb_lgrp_normalize_name(gname))
return (SMB_LGRP_INVALID_NAME);
/* Cannot remove a built-in group */
@@ -344,8 +338,7 @@ smb_lgrp_setcmnt(char *gname, char *cmnt)
sqlite *db;
int rc;
- (void) trim_whitespace(gname);
- if (!smb_lgrp_chkname(gname))
+ if (!smb_lgrp_normalize_name(gname))
return (SMB_LGRP_INVALID_NAME);
if (cmnt && (strlen(cmnt) > SMB_LGRP_COMMENT_MAX))
@@ -372,8 +365,7 @@ smb_lgrp_getcmnt(char *gname, char **cmnt)
sqlite *db;
int rc;
- (void) trim_whitespace(gname);
- if (!smb_lgrp_chkname(gname))
+ if (!smb_lgrp_normalize_name(gname))
return (SMB_LGRP_INVALID_NAME);
if (cmnt == NULL)
@@ -405,8 +397,7 @@ smb_lgrp_setpriv(char *gname, uint8_t priv_lid, boolean_t enable)
sqlite *db;
int rc;
- (void) trim_whitespace(gname);
- if (!smb_lgrp_chkname(gname))
+ if (!smb_lgrp_normalize_name(gname))
return (SMB_LGRP_INVALID_NAME);
if ((priv_lid < SE_MIN_LUID) || (priv_lid > SE_MAX_LUID))
@@ -439,8 +430,7 @@ smb_lgrp_getpriv(char *gname, uint8_t priv_lid, boolean_t *enable)
smb_group_t grp;
int rc;
- (void) trim_whitespace(gname);
- if (!smb_lgrp_chkname(gname))
+ if (!smb_lgrp_normalize_name(gname))
return (SMB_LGRP_INVALID_NAME);
if ((priv_lid < SE_MIN_LUID) || (priv_lid > SE_MAX_LUID))
@@ -471,8 +461,7 @@ smb_lgrp_add_member(char *gname, smb_sid_t *msid, uint16_t sid_type)
smb_gsid_t mid;
int rc;
- (void) trim_whitespace(gname);
- if (!smb_lgrp_chkname(gname))
+ if (!smb_lgrp_normalize_name(gname))
return (SMB_LGRP_INVALID_NAME);
if (!smb_sid_isvalid(msid))
@@ -503,8 +492,7 @@ smb_lgrp_del_member(char *gname, smb_sid_t *msid, uint16_t sid_type)
smb_gsid_t mid;
int rc;
- (void) trim_whitespace(gname);
- if (!smb_lgrp_chkname(gname))
+ if (!smb_lgrp_normalize_name(gname))
return (SMB_LGRP_INVALID_NAME);
if (!smb_sid_isvalid(msid))
@@ -538,8 +526,7 @@ smb_lgrp_getbyname(char *gname, smb_group_t *grp)
sqlite *db;
int rc;
- (void) trim_whitespace(gname);
- if (!smb_lgrp_chkname(gname))
+ if (!smb_lgrp_normalize_name(gname))
return (SMB_LGRP_INVALID_NAME);
db = smb_lgrp_db_open(SMB_LGRP_DB_ORD);
@@ -2127,40 +2114,18 @@ smb_lgrp_decode(smb_group_t *grp, char **values, int infolvl, sqlite *db)
}
/*
- * smb_lgrp_chkname
- *
- * User account names are limited to 20 characters and group names are
- * limited to 256 characters. In addition, account names cannot be terminated
- * by a period and they cannot include commas or any of the following printable
- * characters: ", /, \, [, ], :, |, <, >, +, =, ;, ?, *.
- * Names also cannot include characters in the range 1-31, which are
- * nonprintable.
+ * smb_lgrp_normalize_name
*
- * Source: MSDN, description of NetLocalGroupAdd function.
+ * Trim whitespace, validate the group name and convert it to lowercase.
*/
static boolean_t
-smb_lgrp_chkname(char *name)
+smb_lgrp_normalize_name(char *name)
{
- static char *invalid_chars =
- "\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017"
- "\020\021\022\023\024\025\026\027\030\031"
- "\"/\\[]:|<>+=;,*?";
- int len, i;
-
- if (name == NULL || *name == '\0')
- return (B_FALSE);
+ (void) trim_whitespace(name);
- len = strlen(name);
- if (len > SMB_LGRP_NAME_MAX)
+ if (smb_name_validate_account(name) != ERROR_SUCCESS)
return (B_FALSE);
- if (name[len - 1] == '.')
- return (B_FALSE);
-
- for (i = 0; i < len; i++)
- if (strchr(invalid_chars, name[i]))
- return (B_FALSE);
-
(void) smb_strlwr(name);
return (B_TRUE);
}
@@ -2270,8 +2235,7 @@ smb_lgrp_exists(char *gname)
sqlite *db;
boolean_t rc;
- (void) trim_whitespace(gname);
- if (!smb_lgrp_chkname(gname))
+ if (!smb_lgrp_normalize_name(gname))
return (B_FALSE);
db = smb_lgrp_db_open(SMB_LGRP_DB_ORD);
diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_pwdutil.c b/usr/src/lib/smbsrv/libsmb/common/smb_pwdutil.c
index 1dfa3fbf6f..d8a2d5333e 100644
--- a/usr/src/lib/smbsrv/libsmb/common/smb_pwdutil.c
+++ b/usr/src/lib/smbsrv/libsmb/common/smb_pwdutil.c
@@ -167,7 +167,17 @@ smb_pwd_init(boolean_t create_cache)
{
if (create_cache) {
smb_lucache_create();
+#if 0
+ /*
+ * This pre-loading of the cache results in idmapd requests.
+ * With the change to allow idmapd to call into libsmb to
+ * map names and SIDs, this creates a circular startup
+ * dependency. This call has been temporarily disabled to
+ * avoid this issue. It can be enabled when the name/SID
+ * lookup can be done directly on the LSA service.
+ */
smb_lucache_update();
+#endif
}
smb_pwd_hdl = smb_dlopen();
diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_sd.c b/usr/src/lib/smbsrv/libsmb/common/smb_sd.c
index 74f653e689..af9171ce1d 100644
--- a/usr/src/lib/smbsrv/libsmb/common/smb_sd.c
+++ b/usr/src/lib/smbsrv/libsmb/common/smb_sd.c
@@ -55,7 +55,6 @@ static struct {
static void smb_sd_set_sacl(smb_sd_t *, smb_acl_t *, boolean_t, int);
static void smb_sd_set_dacl(smb_sd_t *, smb_acl_t *, boolean_t, int);
-static uint32_t smb_sd_fromfs(smb_fssd_t *, smb_sd_t *);
void
smb_sd_init(smb_sd_t *sd, uint8_t revision)
@@ -384,7 +383,7 @@ smb_sd_tofs(smb_sd_t *sd, smb_fssd_t *fs_sd)
* Should call smb_sd_term() for the returned sd to free allocated
* members.
*/
-static uint32_t
+uint32_t
smb_sd_fromfs(smb_fssd_t *fs_sd, smb_sd_t *sd)
{
uint32_t status = NT_STATUS_SUCCESS;
diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_util.c b/usr/src/lib/smbsrv/libsmb/common/smb_util.c
index f21d7e477a..41a96a940e 100644
--- a/usr/src/lib/smbsrv/libsmb/common/smb_util.c
+++ b/usr/src/lib/smbsrv/libsmb/common/smb_util.c
@@ -844,3 +844,246 @@ smb_getnameinfo(smb_inaddr_t *ip, char *hostname, int hostlen, int flags)
return (getnameinfo((struct sockaddr *)sp, salen,
hostname, hostlen, NULL, 0, flags));
}
+
+/*
+ * A share name is considered invalid if it contains control
+ * characters or any of the following characters (MSDN 236388).
+ *
+ * " / \ [ ] : | < > + ; , ? * =
+ */
+uint32_t
+smb_name_validate_share(const char *sharename)
+{
+ const char *invalid = "\"/\\[]:|<>+;,?*=";
+ const char *p;
+
+ if (sharename == NULL)
+ return (ERROR_INVALID_PARAMETER);
+
+ if (strpbrk(sharename, invalid) != NULL)
+ return (ERROR_INVALID_NAME);
+
+ for (p = sharename; *p != '\0'; p++) {
+ if (iscntrl(*p))
+ return (ERROR_INVALID_NAME);
+ }
+
+ return (ERROR_SUCCESS);
+}
+
+/*
+ * User and group names are limited to 256 characters, cannot be terminated
+ * by '.' and must not contain control characters or any of the following
+ * characters.
+ *
+ * " / \ [ ] < > + ; , ? * = @
+ */
+uint32_t
+smb_name_validate_account(const char *name)
+{
+ const char *invalid = "\"/\\[]<>+;,?*=@";
+ const char *p;
+ int len;
+
+ if ((name == NULL) || (*name == '\0'))
+ return (ERROR_INVALID_PARAMETER);
+
+ len = strlen(name);
+ if ((len > MAXNAMELEN) || (name[len - 1] == '.'))
+ return (ERROR_INVALID_NAME);
+
+ if (strpbrk(name, invalid) != NULL)
+ return (ERROR_INVALID_NAME);
+
+ for (p = name; *p != '\0'; p++) {
+ if (iscntrl(*p))
+ return (ERROR_INVALID_NAME);
+ }
+
+ return (ERROR_SUCCESS);
+}
+
+/*
+ * Check a domain name for RFC 1035 and 1123 compliance. Domain names may
+ * contain alphanumeric characters, hyphens and dots. The first and last
+ * character of a label must be alphanumeric. Interior characters may be
+ * alphanumeric or hypens.
+ *
+ * Domain names should not contain underscores but we allow them because
+ * Windows names are often in non-compliance with this rule.
+ */
+uint32_t
+smb_name_validate_domain(const char *domain)
+{
+ boolean_t new_label = B_TRUE;
+ const char *p;
+ char label_terminator;
+
+ if (domain == NULL)
+ return (ERROR_INVALID_PARAMETER);
+
+ if (*domain == '\0')
+ return (ERROR_INVALID_NAME);
+
+ label_terminator = *domain;
+
+ for (p = domain; *p != '\0'; ++p) {
+ if (new_label) {
+ if (!isalnum(*p))
+ return (ERROR_INVALID_NAME);
+ new_label = B_FALSE;
+ label_terminator = *p;
+ continue;
+ }
+
+ if (*p == '.') {
+ if (!isalnum(label_terminator))
+ return (ERROR_INVALID_NAME);
+ new_label = B_TRUE;
+ label_terminator = *p;
+ continue;
+ }
+
+ label_terminator = *p;
+
+ if (isalnum(*p) || *p == '-' || *p == '_')
+ continue;
+
+ return (ERROR_INVALID_NAME);
+ }
+
+ if (!isalnum(label_terminator))
+ return (ERROR_INVALID_NAME);
+
+ return (ERROR_SUCCESS);
+}
+
+/*
+ * A NetBIOS domain name can contain letters (a-zA-Z), numbers (0-9) and
+ * hyphens.
+ *
+ * It cannot:
+ * - be blank or longer than 15 chracters
+ * - contain all numbers
+ * - be the same as the computer name
+ */
+uint32_t
+smb_name_validate_nbdomain(const char *name)
+{
+ char netbiosname[NETBIOS_NAME_SZ];
+ const char *p;
+ int len;
+
+ if (name == NULL)
+ return (ERROR_INVALID_PARAMETER);
+
+ len = strlen(name);
+ if (len == 0 || len >= NETBIOS_NAME_SZ)
+ return (ERROR_INVALID_NAME);
+
+ if (strspn(name, "0123456789") == len)
+ return (ERROR_INVALID_NAME);
+
+ if (smb_getnetbiosname(netbiosname, NETBIOS_NAME_SZ) == 0) {
+ if (smb_strcasecmp(name, netbiosname, 0) == 0)
+ return (ERROR_INVALID_NAME);
+ }
+
+ for (p = name; *p != '\0'; ++p) {
+ if (isalnum(*p) || *p == '-' || *p == '_')
+ continue;
+
+ return (ERROR_INVALID_NAME);
+ }
+
+ return (ERROR_SUCCESS);
+}
+
+/*
+ * A workgroup name can contain 1 to 15 characters but cannot be the same
+ * as the NetBIOS name. The name must begin with a letter or number.
+ *
+ * The name cannot consist entirely of spaces or dots, which is covered
+ * by the requirement that the name must begin with an alphanumeric
+ * character.
+ *
+ * The name must not contain control characters or any of the following
+ * characters.
+ *
+ * " / \ [ ] : | < > + = ; , ?
+ */
+uint32_t
+smb_name_validate_workgroup(const char *workgroup)
+{
+ char netbiosname[NETBIOS_NAME_SZ];
+ const char *invalid = "\"/\\[]:|<>+=;,?";
+ const char *p;
+
+ if (workgroup == NULL)
+ return (ERROR_INVALID_PARAMETER);
+
+ if (*workgroup == '\0' || (!isalnum(*workgroup)))
+ return (ERROR_INVALID_NAME);
+
+ if (strlen(workgroup) >= NETBIOS_NAME_SZ)
+ return (ERROR_INVALID_NAME);
+
+ if (smb_getnetbiosname(netbiosname, NETBIOS_NAME_SZ) == 0) {
+ if (smb_strcasecmp(workgroup, netbiosname, 0) == 0)
+ return (ERROR_INVALID_NAME);
+ }
+
+ if (strpbrk(workgroup, invalid) != NULL)
+ return (ERROR_INVALID_NAME);
+
+ for (p = workgroup; *p != '\0'; p++) {
+ if (iscntrl(*p))
+ return (ERROR_INVALID_NAME);
+ }
+
+ return (ERROR_SUCCESS);
+}
+
+/*
+ * Parse a string to obtain the account and domain names as separate strings.
+ *
+ * Names containing a backslash ('\') are known as qualified or composite
+ * names. The string preceding the backslash should be the domain name
+ * and the string following the slash should be a name within that domain.
+ *
+ * Names that do not contain a backslash are known as isolated names.
+ * An isolated name may be a single label, such as john, or may be in
+ * user principal name (UPN) form, such as john@example.com.
+ *
+ * domain\name
+ * domain/name
+ * name
+ * name@domain
+ *
+ * If we encounter any of the forms above in arg, the @, / or \ separator
+ * is replaced by \0 and the name and domain pointers are set to point to
+ * the appropriate components in arg. Otherwise, name and domain pointers
+ * will be set to NULL.
+ */
+void
+smb_name_parse(char *arg, char **account, char **domain)
+{
+ char *p;
+
+ *account = NULL;
+ *domain = NULL;
+
+ if ((p = strpbrk(arg, "/\\@")) != NULL) {
+ if (*p == '@') {
+ *p = '\0';
+ ++p;
+ *domain = p;
+ *account = arg;
+ } else {
+ *p = '\0';
+ ++p;
+ *account = p;
+ *domain = arg;
+ }
+ }
+}
diff --git a/usr/src/lib/smbsrv/libsmbns/common/smbns_ads.c b/usr/src/lib/smbsrv/libsmbns/common/smbns_ads.c
index 5ec6bb0915..a54cf7123d 100644
--- a/usr/src/lib/smbsrv/libsmbns/common/smbns_ads.c
+++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_ads.c
@@ -202,6 +202,7 @@ static boolean_t smb_ads_is_sought_host(smb_ads_host_info_t *, char *);
static boolean_t smb_ads_is_same_domain(char *, char *);
static boolean_t smb_ads_is_pdc_configured(void);
static smb_ads_host_info_t *smb_ads_dup_host_info(smb_ads_host_info_t *);
+static char *smb_ads_get_sharedn(const char *, const char *, const char *);
/*
* smb_ads_init
@@ -1275,6 +1276,46 @@ smb_ads_free_spnset(char **spn_set)
}
/*
+ * Returns share DN in an allocated buffer. The format of the DN is
+ * cn=<sharename>,<container RDNs>,<domain DN>
+ *
+ * If the domain DN is not included in the container parameter,
+ * then it will be appended to create the share DN.
+ *
+ * The caller must free the allocated buffer.
+ */
+static char *
+smb_ads_get_sharedn(const char *sharename, const char *container,
+ const char *domain_dn)
+{
+ char *share_dn;
+ int rc, offset, container_len, domain_len;
+ boolean_t append_domain = B_TRUE;
+
+ container_len = strlen(container);
+ domain_len = strlen(domain_dn);
+
+ if (container_len >= domain_len) {
+
+ /* offset to last domain_len characters */
+ offset = container_len - domain_len;
+
+ if (smb_strcasecmp(container + offset,
+ domain_dn, domain_len) == 0)
+ append_domain = B_FALSE;
+ }
+
+ if (append_domain)
+ rc = asprintf(&share_dn, "cn=%s,%s,%s", sharename,
+ container, domain_dn);
+ else
+ rc = asprintf(&share_dn, "cn=%s,%s", sharename,
+ container);
+
+ return ((rc == -1) ? NULL : share_dn);
+}
+
+/*
* smb_ads_add_share
* Call by smb_ads_publish_share to create share object in ADS.
* This routine specifies the attributes of an ADS LDAP share object. The first
@@ -1299,19 +1340,13 @@ smb_ads_add_share(smb_ads_handle_t *ah, const char *adsShareName,
LDAPMod *attrs[SMB_ADS_SHARE_NUM_ATTR];
int j = 0;
char *share_dn;
- int len, ret;
+ int ret;
char *unc_names[] = {(char *)unc_name, NULL};
- len = 5 + strlen(adsShareName) + strlen(adsContainer) +
- strlen(ah->domain_dn) + 1;
-
- share_dn = (char *)malloc(len);
- if (share_dn == NULL)
+ if ((share_dn = smb_ads_get_sharedn(adsShareName, adsContainer,
+ ah->domain_dn)) == NULL)
return (-1);
- (void) snprintf(share_dn, len, "cn=%s,%s,%s", adsShareName,
- adsContainer, ah->domain_dn);
-
if (smb_ads_alloc_attr(attrs, SMB_ADS_SHARE_NUM_ATTR) != 0) {
free(share_dn);
return (-1);
@@ -1355,17 +1390,12 @@ smb_ads_del_share(smb_ads_handle_t *ah, const char *adsShareName,
const char *adsContainer)
{
char *share_dn;
- int len, ret;
-
- len = 5 + strlen(adsShareName) + strlen(adsContainer) +
- strlen(ah->domain_dn) + 1;
+ int ret;
- share_dn = (char *)malloc(len);
- if (share_dn == NULL)
+ if ((share_dn = smb_ads_get_sharedn(adsShareName, adsContainer,
+ ah->domain_dn)) == NULL)
return (-1);
- (void) snprintf(share_dn, len, "cn=%s,%s,%s", adsShareName,
- adsContainer, ah->domain_dn);
if ((ret = ldap_delete_s(ah->ld, share_dn)) != LDAP_SUCCESS) {
smb_tracef("ldap_delete: %s", ldap_err2string(ret));
free(share_dn);
@@ -1450,23 +1480,17 @@ smb_ads_lookup_share(smb_ads_handle_t *ah, const char *adsShareName,
{
char *attrs[4], filter[SMB_ADS_MAXBUFLEN];
char *share_dn;
- int len, ret;
+ int ret;
LDAPMessage *res;
char tmpbuf[SMB_ADS_MAXBUFLEN];
if (adsShareName == NULL || adsContainer == NULL)
return (-1);
- len = 5 + strlen(adsShareName) + strlen(adsContainer) +
- strlen(ah->domain_dn) + 1;
-
- share_dn = (char *)malloc(len);
- if (share_dn == NULL)
+ if ((share_dn = smb_ads_get_sharedn(adsShareName, adsContainer,
+ ah->domain_dn)) == NULL)
return (-1);
- (void) snprintf(share_dn, len, "cn=%s,%s,%s", adsShareName,
- adsContainer, ah->domain_dn);
-
res = NULL;
attrs[0] = "cn";
attrs[1] = "objectClass";