diff options
Diffstat (limited to 'usr/src/lib')
86 files changed, 5855 insertions, 6767 deletions
diff --git a/usr/src/lib/Makefile b/usr/src/lib/Makefile index 0aec8857f3..02d7c65ca7 100644 --- a/usr/src/lib/Makefile +++ b/usr/src/lib/Makefile @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -553,7 +553,7 @@ libshare: libscf libzfs libuuid libfsmgt libsecdb libexacct/demo: libexacct libproject libsocket libnsl libtsalarm: libpcp smbsrv: libsocket libnsl libmd libxnet libpthread librt \ - libshare libidmap pkcs11 + libshare libidmap pkcs11 libsqlite libvscan: libscf # diff --git a/usr/src/lib/libshare/common/libshare.c b/usr/src/lib/libshare/common/libshare.c index 5716ef931c..74bb0af7e9 100644 --- a/usr/src/lib/libshare/common/libshare.c +++ b/usr/src/lib/libshare/common/libshare.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -217,15 +217,6 @@ sa_errorstr(int err) case SA_PATH_IS_PARENTDIR: ret = dgettext(TEXT_DOMAIN, "path is parent of a share"); break; - case SA_KRB_KEYTAB_ERR: - ret = dgettext(TEXT_DOMAIN, "unable to remove the old keys" - " from the Kerberos keytab. Please manually remove" - " the old keys for your host principal prior to setting" - " the ads_domain property"); - break; - case SA_NO_SERVICE: - ret = dgettext(TEXT_DOMAIN, "service is not running"); - break; default: (void) snprintf(errstr, sizeof (errstr), dgettext(TEXT_DOMAIN, "unknown %d"), err); diff --git a/usr/src/lib/libshare/common/libshare.h b/usr/src/lib/libshare/common/libshare.h index af6e2db2f8..b45b747d9a 100644 --- a/usr/src/lib/libshare/common/libshare.h +++ b/usr/src/lib/libshare/common/libshare.h @@ -20,7 +20,7 @@ */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -85,8 +85,6 @@ typedef void *sa_handle_t; /* opaque handle to access core functions */ #define SA_MULTIPLE_ERROR 26 /* multiple protocols reported error */ #define SA_PATH_IS_SUBDIR 27 /* check_path found path is subdir */ #define SA_PATH_IS_PARENTDIR 28 /* check_path found path is parent */ -#define SA_KRB_KEYTAB_ERR 29 /* fail to delete old keytab entries */ -#define SA_NO_SERVICE 30 /* service isn't running */ /* API Initialization */ #define SA_INIT_SHARE_API 0x0001 /* init share specific interface */ diff --git a/usr/src/lib/libshare/smb/libshare_smb.c b/usr/src/lib/libshare/smb/libshare_smb.c index 9aa98e9a37..0a3ed7535b 100644 --- a/usr/src/lib/libshare/smb/libshare_smb.c +++ b/usr/src/lib/libshare/smb/libshare_smb.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -77,18 +77,21 @@ static int string_length_check_validator(int, char *); static int true_false_validator(int, char *); static int ip_address_validator_empty_ok(int, char *); static int ip_address_csv_list_validator_empty_ok(int, char *); -static int ipc_mode_validator(int, char *); static int path_validator(int, char *); static int smb_enable_resource(sa_resource_t); static int smb_disable_resource(sa_resource_t); static uint64_t smb_share_features(void); static int smb_list_transient(sa_handle_t); -static int smb_domain_change_event(char *new_domain); + +extern void lmshrd_door_close(void); /* size of basic format allocation */ #define OPT_CHUNK 1024 +/* size of string for types - big enough to hold "dependency" */ +#define SCFTYPE_LEN 32 + /* * Indexes of entries in smb_proto_options table. * Changes to smb_proto_options table may require @@ -245,6 +248,50 @@ smb_isonline(void) } /* + * smb_isdisabled() + * + * Determine if the SMF service instance is in the disabled state or + * not. A number of operations depend on this state. + */ +static boolean_t +smb_isdisabled(void) +{ + char *str; + boolean_t ret = B_FALSE; + + if ((str = smf_get_state(SMBD_DEFAULT_INSTANCE_FMRI)) != NULL) { + ret = (strcmp(str, SCF_STATE_STRING_DISABLED) == 0); + free(str); + } + return (ret); +} + +/* + * smb_isautoenable() + * + * Determine if the SMF service instance auto_enabled set or not. A + * number of operations depend on this state. The property not being + * set or being set to true means autoenable. Only being set to false + * is not autoenabled. + */ +static boolean_t +smb_isautoenable(void) +{ + boolean_t ret = B_TRUE; + scf_simple_prop_t *prop; + uint8_t *retstr; + + prop = scf_simple_prop_get(NULL, SMBD_DEFAULT_INSTANCE_FMRI, + "application", "auto_enable"); + if (prop != NULL) { + retstr = scf_simple_prop_next_boolean(prop); + ret = *retstr != 0; + scf_simple_prop_free(prop); + } + return (ret); +} + +/* * smb_enable_share tells the implementation that it is to enable the share. * This entails converting the path and options into the appropriate ioctl * calls. It is assumed that all error checking of paths, etc. were @@ -273,7 +320,12 @@ smb_enable_share(sa_share_t share) if (path == NULL) return (SA_NO_SUCH_PATH); + /* + * If administratively disabled, don't try to start anything. + */ online = smb_isonline(); + if (!online && !smb_isautoenable() && smb_isdisabled()) + goto done; iszfs = sa_path_is_zfs(path); @@ -374,11 +426,28 @@ smb_enable_resource(sa_resource_t resource) sa_optionset_t opts; sa_share_t share; lmshare_info_t si; - int ret; + int ret = SA_OK; + int err; + boolean_t isonline; share = sa_get_resource_parent(resource); if (share == NULL) return (SA_NO_SUCH_PATH); + + /* + * If administratively disabled, don't try to start anything. + */ + isonline = smb_isonline(); + if (!isonline && !smb_isautoenable() && smb_isdisabled()) + goto done; + + if (!isonline) + ret = smb_enable_service(); + if (!smb_isonline()) { + ret = SA_OK; + goto done; + } + path = sa_get_share_attr(share, "path"); if (path == NULL) return (SA_SYSTEM_ERR); @@ -388,21 +457,25 @@ smb_enable_resource(sa_resource_t resource) return (SA_NO_SUCH_RESOURCE); } - ret = smb_enable_service(); - - if (!smb_isonline()) { - ret = SA_OK; - goto done; - } - opts = sa_get_derived_optionset(resource, SMB_PROTOCOL_NAME, 1); smb_build_lmshare_info(rname, path, opts, &si); sa_free_attr_string(path); sa_free_attr_string(rname); sa_free_derived_optionset(opts); - if (lmshrd_add(&si) != NERR_Success) + + /* + * Attempt to add the share. Any error that occurs if it was + * online is an error but don't count NERR_DuplicateName if + * smb/server had to be brought online since bringing the + * service up will enable the share that was just added prior + * to the attempt to enable. + */ + + err = lmshrd_add(&si); + if (err == NERR_Success || !(!isonline && err == NERR_DuplicateName)) + (void) sa_update_sharetab(share, "smb"); + else return (SA_NOT_SHARED); - (void) sa_update_sharetab(share, "smb"); done: return (ret); @@ -670,85 +743,44 @@ smb_validate_property(sa_property_t property, sa_optionset_t parent) */ struct smb_proto_option_defs { - char *name; /* display name -- remove protocol identifier */ int smb_index; int32_t minval; int32_t maxval; /* In case of length of string this should be max */ int (*validator)(int, char *); int32_t refresh; } smb_proto_options[] = { - { SMB_CD_SYS_CMNT, - SMB_CI_SYS_CMNT, 0, MAX_VALUE_BUFLEN, - string_length_check_validator, SMB_REFRESH_REFRESH}, - { SMB_CD_MAX_WORKERS, - SMB_CI_MAX_WORKERS, 64, 1024, range_check_validator, - SMB_REFRESH_REFRESH}, - { SMB_CD_NBSCOPE, - SMB_CI_NBSCOPE, 0, MAX_VALUE_BUFLEN, - string_length_check_validator, SMB_REFRESH_REFRESH}, - { SMB_CD_RDR_IPCMODE, - SMB_CI_RDR_IPCMODE, 0, 0, ipc_mode_validator, SMB_REFRESH_REFRESH}, - { SMB_CD_LM_LEVEL, - SMB_CI_LM_LEVEL, 2, 5, range_check_validator, SMB_REFRESH_REFRESH}, - { SMB_CD_KEEPALIVE, - SMB_CI_KEEPALIVE, 20, 5400, range_check_validator_zero_ok, - SMB_REFRESH_REFRESH}, - { SMB_CD_WINS_SRV1, - SMB_CI_WINS_SRV1, 0, MAX_VALUE_BUFLEN, - ip_address_validator_empty_ok, SMB_REFRESH_REFRESH}, - { SMB_CD_WINS_SRV2, - SMB_CI_WINS_SRV2, 0, MAX_VALUE_BUFLEN, - ip_address_validator_empty_ok, SMB_REFRESH_REFRESH}, - { SMB_CD_WINS_EXCL, - SMB_CI_WINS_EXCL, 0, MAX_VALUE_BUFLEN, - ip_address_csv_list_validator_empty_ok, SMB_REFRESH_REFRESH}, - { SMB_CD_SIGNING_ENABLE, - SMB_CI_SIGNING_ENABLE, 0, 0, true_false_validator, - SMB_REFRESH_REFRESH}, - { SMB_CD_SIGNING_REQD, - SMB_CI_SIGNING_REQD, 0, 0, true_false_validator, - SMB_REFRESH_REFRESH}, - { SMB_CD_RESTRICT_ANON, - SMB_CI_RESTRICT_ANON, 0, 0, true_false_validator, - SMB_REFRESH_REFRESH}, - { SMB_CD_DOMAIN_SRV, - SMB_CI_DOMAIN_SRV, 0, MAX_VALUE_BUFLEN, - ip_address_validator_empty_ok, SMB_REFRESH_REFRESH}, - { SMB_CD_ADS_ENABLE, - SMB_CI_ADS_ENABLE, 0, 0, true_false_validator, SMB_REFRESH_REFRESH}, - { SMB_CD_ADS_USER, - SMB_CI_ADS_USER, 0, MAX_VALUE_BUFLEN, - string_length_check_validator, SMB_REFRESH_REFRESH}, - { SMB_CD_ADS_USER_CONTAINER, - SMB_CI_ADS_USER_CONTAINER, 0, MAX_VALUE_BUFLEN, - string_length_check_validator, SMB_REFRESH_REFRESH}, - { SMB_CD_ADS_DOMAIN, - SMB_CI_ADS_DOMAIN, 0, MAX_VALUE_BUFLEN, - string_length_check_validator, SMB_REFRESH_REFRESH}, - { SMB_CD_ADS_PASSWD, - SMB_CI_ADS_PASSWD, 0, MAX_VALUE_BUFLEN, - string_length_check_validator, SMB_REFRESH_REFRESH}, - { SMB_CD_ADS_IPLOOKUP, - SMB_CI_ADS_IPLOOKUP, 0, 0, true_false_validator, - SMB_REFRESH_REFRESH}, - { SMB_CD_ADS_SITE, - SMB_CI_ADS_SITE, 0, MAX_VALUE_BUFLEN, - string_length_check_validator, SMB_REFRESH_REFRESH}, - { SMB_CD_DYNDNS_ENABLE, - SMB_CI_DYNDNS_ENABLE, 0, 0, true_false_validator, - SMB_REFRESH_REFRESH}, - { SMB_CD_DYNDNS_RETRY_SEC, - SMB_CI_DYNDNS_RETRY_SEC, 0, 20, range_check_validator, - SMB_REFRESH_REFRESH}, - { SMB_CD_DYNDNS_RETRY_COUNT, - SMB_CI_DYNDNS_RETRY_COUNT, 3, 5, range_check_validator, - SMB_REFRESH_REFRESH}, - { SMB_CD_AUTOHOME_MAP, - SMB_CI_AUTOHOME_MAP, 0, MAX_VALUE_BUFLEN, - path_validator}, - {NULL, -1, 0, 0, NULL} + { SMB_CI_SYS_CMNT, 0, MAX_VALUE_BUFLEN, + string_length_check_validator, SMB_REFRESH_REFRESH }, + { SMB_CI_MAX_WORKERS, 64, 1024, range_check_validator, + SMB_REFRESH_REFRESH }, + { SMB_CI_NBSCOPE, 0, MAX_VALUE_BUFLEN, + string_length_check_validator, 0 }, + { SMB_CI_LM_LEVEL, 2, 5, range_check_validator, 0 }, + { SMB_CI_KEEPALIVE, 20, 5400, range_check_validator_zero_ok, + SMB_REFRESH_REFRESH }, + { SMB_CI_WINS_SRV1, 0, MAX_VALUE_BUFLEN, + ip_address_validator_empty_ok, SMB_REFRESH_REFRESH }, + { SMB_CI_WINS_SRV2, 0, MAX_VALUE_BUFLEN, + ip_address_validator_empty_ok, SMB_REFRESH_REFRESH }, + { SMB_CI_WINS_EXCL, 0, MAX_VALUE_BUFLEN, + ip_address_csv_list_validator_empty_ok, SMB_REFRESH_REFRESH }, + { SMB_CI_SIGNING_ENABLE, 0, 0, true_false_validator, + SMB_REFRESH_REFRESH }, + { SMB_CI_SIGNING_REQD, 0, 0, true_false_validator, + SMB_REFRESH_REFRESH }, + { SMB_CI_RESTRICT_ANON, 0, 0, true_false_validator, + SMB_REFRESH_REFRESH }, + { SMB_CI_DOMAIN_SRV, 0, MAX_VALUE_BUFLEN, + ip_address_validator_empty_ok, 0 }, + { SMB_CI_ADS_SITE, 0, MAX_VALUE_BUFLEN, + string_length_check_validator, SMB_REFRESH_REFRESH }, + { SMB_CI_DYNDNS_ENABLE, 0, 0, true_false_validator, 0 }, + { SMB_CI_AUTOHOME_MAP, 0, MAX_VALUE_BUFLEN, path_validator, 0 }, }; +#define SMB_OPT_NUM \ + (sizeof (smb_proto_options) / sizeof (smb_proto_options[0])) + /* * Check the range of value as int range. */ @@ -884,22 +916,6 @@ ip_address_csv_list_validator_empty_ok(int index, char *value) } /* - * Check IPC mode - */ -/*ARGSUSED*/ -static int -ipc_mode_validator(int index, char *value) -{ - if (value == NULL) - return (SA_BAD_VALUE); - if (strcasecmp(value, "anon") == 0) - return (SA_OK); - if (strcasecmp(value, "auth") == 0) - return (SA_OK); - return (SA_BAD_VALUE); -} - -/* * Check path */ /*ARGSUSED*/ @@ -937,10 +953,14 @@ static int findprotoopt(char *name) { int i; - for (i = 0; smb_proto_options[i].name != NULL; i++) { - if (strcasecmp(smb_proto_options[i].name, name) == 0) + char *sc_name; + + for (i = 0; i < SMB_OPT_NUM; i++) { + sc_name = smb_config_getname(smb_proto_options[i].smb_index); + if (strcasecmp(sc_name, name) == 0) return (i); } + return (-1); } @@ -954,21 +974,22 @@ static int smb_load_proto_properties() { sa_property_t prop; + char value[MAX_VALUE_BUFLEN]; + char *name; int index; - char *value; + int rc; protoset = sa_create_protocol_properties(SMB_PROTOCOL_NAME); if (protoset == NULL) return (SA_NO_MEMORY); - if (smb_config_load() != 0) - return (SA_CONFIG_ERR); - for (index = 0; smb_proto_options[index].name != NULL; index++) { - value = smb_config_getenv(smb_proto_options[index].smb_index); - prop = sa_create_property( - smb_proto_options[index].name, value != NULL ? value : ""); - if (value != NULL) - free(value); + for (index = 0; index < SMB_OPT_NUM; index++) { + rc = smb_config_get(smb_proto_options[index].smb_index, + value, sizeof (value)); + if (rc != SMBD_SMF_OK) + continue; + name = smb_config_getname(smb_proto_options[index].smb_index); + prop = sa_create_property(name, value); if (prop != NULL) (void) sa_add_protocol_property(protoset, prop); } @@ -1004,6 +1025,8 @@ smb_share_fini(void) { xmlFreeNode(protoset); protoset = NULL; + + (void) lmshrd_door_close(); } /* @@ -1019,6 +1042,140 @@ smb_get_proto_set(void) } /* + * smb_enable_dependencies() + * + * SMBD_DEFAULT_INSTANCE_FMRI may have some dependencies that aren't + * enabled. This will attempt to enable all of them. + */ +static void +smb_enable_dependencies(const char *fmri) +{ + scf_handle_t *handle; + scf_service_t *service; + scf_instance_t *inst = NULL; + scf_iter_t *iter; + scf_property_t *prop; + scf_value_t *value; + scf_propertygroup_t *pg; + scf_scope_t *scope; + char type[SCFTYPE_LEN]; + char *dependency; + char *servname; + int maxlen; + + /* + * Get all required handles and storage. + */ + handle = scf_handle_create(SCF_VERSION); + if (handle == NULL) + return; + + if (scf_handle_bind(handle) != 0) { + scf_handle_destroy(handle); + return; + } + + maxlen = scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH); + if (maxlen == (ssize_t)-1) + maxlen = MAXPATHLEN; + + dependency = malloc(maxlen); + + service = scf_service_create(handle); + + iter = scf_iter_create(handle); + + pg = scf_pg_create(handle); + + prop = scf_property_create(handle); + + value = scf_value_create(handle); + + scope = scf_scope_create(handle); + + if (service == NULL || iter == NULL || pg == NULL || prop == NULL || + value == NULL || scope == NULL || dependency == NULL) + goto done; + + /* + * We passed in the FMRI for the default instance but for + * some things we need the simple form so construct it. Since + * we reuse the storage that dependency points to, we need to + * use the servname early. + */ + (void) snprintf(dependency, maxlen, "%s", fmri + sizeof ("svc:")); + servname = strrchr(dependency, ':'); + if (servname == NULL) + goto done; + *servname = '\0'; + servname = dependency; + + /* + * Setup to iterate over the service property groups, only + * looking at those that are "dependency" types. The "entity" + * property will have the FMRI of the service we are dependent + * on. + */ + if (scf_handle_get_scope(handle, SCF_SCOPE_LOCAL, scope) != 0) + goto done; + + if (scf_scope_get_service(scope, servname, service) != 0) + goto done; + + if (scf_iter_service_pgs(iter, service) != 0) + goto done; + + while (scf_iter_next_pg(iter, pg) > 0) { + char *services[2]; + /* + * Have a property group for the service. See if it is + * a dependency pg and only do operations on those. + */ + if (scf_pg_get_type(pg, type, SCFTYPE_LEN) <= 0) + continue; + + if (strncmp(type, SCF_GROUP_DEPENDENCY, SCFTYPE_LEN) != 0) + continue; + /* + * Have a dependency. Attempt to enable it. + */ + if (scf_pg_get_property(pg, SCF_PROPERTY_ENTITIES, prop) != 0) + continue; + + if (scf_property_get_value(prop, value) != 0) + continue; + + services[1] = NULL; + + if (scf_value_get_as_string(value, dependency, maxlen) > 0) { + services[0] = dependency; + _check_services(services); + } + } + +done: + if (dependency != NULL) + free(dependency); + if (value != NULL) + scf_value_destroy(value); + if (prop != NULL) + scf_property_destroy(prop); + if (pg != NULL) + scf_pg_destroy(pg); + if (iter != NULL) + scf_iter_destroy(iter); + if (scope != NULL) + scf_scope_destroy(scope); + if (inst != NULL) + scf_instance_destroy(inst); + if (service != NULL) + scf_service_destroy(service); + + (void) scf_handle_unbind(handle); + scf_handle_destroy(handle); +} + +/* * How long to wait for service to come online */ #define WAIT_FOR_SERVICE 15 @@ -1032,21 +1189,25 @@ smb_enable_service(void) { int i; int ret = SA_OK; + char *service[] = { SMBD_DEFAULT_INSTANCE_FMRI, NULL }; if (!smb_isonline()) { - if (smf_enable_instance(SMBD_DEFAULT_INSTANCE_FMRI, 0) != 0) { - (void) fprintf(stderr, - dgettext(TEXT_DOMAIN, - "%s failed to restart: %s\n"), - SMBD_DEFAULT_INSTANCE_FMRI, - scf_strerror(scf_error())); - return (SA_CONFIG_ERR); - } + /* + * Attempt to start the idmap, and other dependent + * services, first. If it fails, the SMB service will + * ultimately fail so we use that as the error. If we + * don't try to enable idmap, smb won't start the + * first time unless the admin has done it + * manually. The service could be administratively + * disabled so we won't always get started. + */ + smb_enable_dependencies(SMBD_DEFAULT_INSTANCE_FMRI); + _check_services(service); /* Wait for service to come online */ for (i = 0; i < WAIT_FOR_SERVICE; i++) { if (smb_isonline()) { - ret = SA_OK; + ret = SA_OK; break; } else { ret = SA_BUSY; @@ -1079,45 +1240,6 @@ smb_validate_proto_prop(int index, char *name, char *value) } /* - * smb_domain_change_event - * - * This function is called whenever ads_domain is changed via sharectl. - * It will make a door call to trigger the ADS domain change event. - */ -static int -smb_domain_change_event(char *new_domain) -{ - char *orig_domain; - int rc = SA_OK; - - orig_domain = smb_config_getenv(SMB_CI_ADS_DOMAIN); - if (orig_domain == NULL) - return (rc); - - if (strcasecmp(orig_domain, new_domain) == 0) { - free(orig_domain); - return (rc); - } - - if (!smb_isonline()) { - free(orig_domain); - return (SA_NO_SERVICE); - } - - /* - * Clear the ADS_HOST_INFO cache - * and remove old keys from the - * Kerberos keytab. - */ - if (smb_ads_domain_change_notify(orig_domain) != 0) - rc = SA_KRB_KEYTAB_ERR; - - free(orig_domain); - return (rc); -} - - -/* * smb_set_proto_prop(prop) * * check that prop is valid. @@ -1141,13 +1263,9 @@ smb_set_proto_prop(sa_property_t prop) ret = smb_validate_proto_prop(index, name, value); if (ret == SA_OK) { opt = &smb_proto_options[index]; - if ((opt->smb_index == SMB_CI_ADS_DOMAIN) && - (ret = smb_domain_change_event(value)) - != SA_OK) - goto cleanup; /* Save to SMF */ - smb_config_setenv(opt->smb_index, value); + (void) smb_config_set(opt->smb_index, value); /* * Specialized refresh mechanisms can * be flagged in the proto_options and @@ -1162,7 +1280,6 @@ smb_set_proto_prop(sa_property_t prop) } } -cleanup: if (name != NULL) sa_free_attr_string(name); if (value != NULL) diff --git a/usr/src/lib/libshare/smb/smb_share_doorclnt.c b/usr/src/lib/libshare/smb/smb_share_doorclnt.c index 0ebf61b7a9..1a06278568 100644 --- a/usr/src/lib/libshare/smb/smb_share_doorclnt.c +++ b/usr/src/lib/libshare/smb/smb_share_doorclnt.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -37,15 +37,20 @@ #include <errno.h> #include <string.h> #include <strings.h> +#include <unistd.h> +#include <thread.h> +#include <synch.h> #include <smbsrv/libsmb.h> - #include <smbsrv/lmshare.h> #include <smbsrv/lmerr.h> #include <smbsrv/lmshare_door.h> #include <smbsrv/cifs.h> -int lmshrd_fildes = -1; +static int lmshrd_fildes = -1; +static uint64_t lmshrd_door_ncall = 0; +static mutex_t lmshrd_mutex; +static cond_t lmshrd_cv; char *lmshrd_desc[] = { "", @@ -72,116 +77,150 @@ char *lmshrd_desc[] = { }; /* - * Returns 0 on success. Otherwise, -1. + * Open the lmshrd door. This is a private call for use by + * lmshrd_door_enter() and must be called with lmshrd_mutex held. + * + * Returns the door fd on success. Otherwise, -1. */ static int -lmshrd_door_open(int opcode) +lmshrd_door_open(void) +{ + if (lmshrd_fildes == -1) { + if ((lmshrd_fildes = open(LMSHR_DOOR_NAME, O_RDONLY)) < 0) + lmshrd_fildes = -1; + else + lmshrd_door_ncall = 0; + } + + return (lmshrd_fildes); +} + +/* + * Close the lmshrd door. + */ +void +lmshrd_door_close(void) { - int rc = 0; + (void) mutex_lock(&lmshrd_mutex); - if (lmshrd_fildes == -1 && - (lmshrd_fildes = open(LMSHR_DOOR_NAME, O_RDONLY)) < 0) { - syslog(LOG_DEBUG, "%s: open %s failed %s", lmshrd_desc[opcode], - LMSHR_DOOR_NAME, strerror(errno)); - rc = -1; + if (lmshrd_fildes != -1) { + while (lmshrd_door_ncall > 0) + (void) cond_wait(&lmshrd_cv, &lmshrd_mutex); + + if (lmshrd_fildes != -1) { + (void) close(lmshrd_fildes); + lmshrd_fildes = -1; + } } - return (rc); + + (void) mutex_unlock(&lmshrd_mutex); } /* - * Return 0 upon success. Otherwise, -1. + * Entry handler for lmshrd door calls. */ -static int -lmshrd_door_check_srv_status(int opcode, smb_dr_ctx_t *dec_ctx) +static door_arg_t * +lmshrd_door_enter(void) { - int status = smb_dr_get_int32(dec_ctx); - int err; - int rc = -1; + door_arg_t *arg; + char *buf; - switch (status) { - case LMSHR_DOOR_SRV_SUCCESS: - rc = 0; - break; + (void) mutex_lock(&lmshrd_mutex); - case LMSHR_DOOR_SRV_ERROR: - err = smb_dr_get_uint32(dec_ctx); - syslog(LOG_ERR, "%s: Encountered door server error %s", - lmshrd_desc[opcode], strerror(err)); - break; + if (lmshrd_door_open() == -1) { + (void) mutex_unlock(&lmshrd_mutex); + return (NULL); + } + + if ((arg = malloc(sizeof (door_arg_t) + LMSHR_DOOR_SIZE)) != NULL) { + buf = ((char *)arg) + sizeof (door_arg_t); + bzero(arg, sizeof (door_arg_t)); + arg->data_ptr = buf; + arg->rbuf = buf; + arg->rsize = LMSHR_DOOR_SIZE; - default: - syslog(LOG_ERR, "%s: Unknown door server status", - lmshrd_desc[opcode]); + ++lmshrd_door_ncall; } - if (rc != 0) { - if ((err = smb_dr_decode_finish(dec_ctx)) != 0) - syslog(LOG_ERR, "%s: Decode error %s", - lmshrd_desc[opcode], strerror(err)); + (void) mutex_unlock(&lmshrd_mutex); + return (arg); +} + +/* + * Exit handler for lmshrd door calls. + */ +static void +lmshrd_door_exit(door_arg_t *arg, char *errmsg) +{ + if (errmsg) + syslog(LOG_DEBUG, "lmshrd_door: %s", errmsg); + + (void) mutex_lock(&lmshrd_mutex); + free(arg); + --lmshrd_door_ncall; + (void) cond_signal(&lmshrd_cv); + (void) mutex_unlock(&lmshrd_mutex); +} + +/* + * Return 0 upon success. Otherwise, -1. + */ +static int +lmshrd_door_check_status(smb_dr_ctx_t *dec_ctx) +{ + int status = smb_dr_get_int32(dec_ctx); + + if (status != LMSHR_DOOR_SRV_SUCCESS) { + if (status == LMSHR_DOOR_SRV_ERROR) + (void) smb_dr_get_uint32(dec_ctx); + return (-1); } - return (rc); + return (0); } uint64_t lmshrd_open_iterator(int mode) { - door_arg_t arg; - char *buf; - unsigned int used; + door_arg_t *arg; smb_dr_ctx_t *dec_ctx; smb_dr_ctx_t *enc_ctx; - unsigned int status = 0; uint64_t lmshr_iter = 0; - int opcode = LMSHR_DOOR_OPEN_ITERATOR; + int rc; - if (lmshrd_door_open(opcode) == -1) + if ((arg = lmshrd_door_enter()) == NULL) return (lmshr_iter); - buf = malloc(LMSHR_DOOR_SIZE); - if (!buf) - return (lmshr_iter); - - enc_ctx = smb_dr_encode_start(buf, LMSHR_DOOR_SIZE); - smb_dr_put_uint32(enc_ctx, opcode); + enc_ctx = smb_dr_encode_start(arg->data_ptr, LMSHR_DOOR_SIZE); + smb_dr_put_uint32(enc_ctx, LMSHR_DOOR_OPEN_ITERATOR); smb_dr_put_int32(enc_ctx, mode); - if ((status = smb_dr_encode_finish(enc_ctx, &used)) != 0) { - syslog(LOG_ERR, "%s: Encode error %s", - lmshrd_desc[opcode], strerror(status)); - (void) free(buf); + + rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size); + if (rc != 0) { + lmshrd_door_exit(arg, "encode error"); return (lmshr_iter); } - arg.data_ptr = buf; - arg.data_size = used; - arg.desc_ptr = NULL; - arg.desc_num = 0; - arg.rbuf = buf; - arg.rsize = LMSHR_DOOR_SIZE; - - if (door_call(lmshrd_fildes, &arg) < 0) { - syslog(LOG_DEBUG, "%s: Door call failed %s", - lmshrd_desc[opcode], strerror(errno)); - (void) free(buf); - lmshrd_fildes = -1; + if (door_call(lmshrd_fildes, arg) < 0) { + lmshrd_door_exit(arg, "door call error"); + lmshrd_door_close(); return (lmshr_iter); } - dec_ctx = smb_dr_decode_start(arg.data_ptr, arg.data_size); - if (lmshrd_door_check_srv_status(opcode, dec_ctx) != 0) { - (void) free(buf); + dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size); + if (lmshrd_door_check_status(dec_ctx) != 0) { + (void) smb_dr_decode_finish(dec_ctx); + lmshrd_door_exit(arg, "decode error"); return (lmshr_iter); } lmshr_iter = smb_dr_get_lmshr_iterator(dec_ctx); - if ((status = smb_dr_decode_finish(dec_ctx)) != 0) { - syslog(LOG_ERR, "%s: Decode error %s", - lmshrd_desc[opcode], strerror(status)); - (void) free(buf); + if (smb_dr_decode_finish(dec_ctx) != 0) { + lmshrd_door_exit(arg, "decode error"); return (lmshr_iter); } - (void) free(buf); + lmshrd_door_exit(arg, NULL); return (lmshr_iter); } @@ -189,312 +228,221 @@ lmshrd_open_iterator(int mode) DWORD lmshrd_close_iterator(uint64_t iterator) { - door_arg_t arg; - char *buf; - unsigned int used; + door_arg_t *arg; smb_dr_ctx_t *dec_ctx; smb_dr_ctx_t *enc_ctx; - unsigned int status = 0; - int opcode = LMSHR_DOOR_CLOSE_ITERATOR; - - if (lmshrd_door_open(opcode) == -1) - return (NERR_InternalError); + int rc; - buf = malloc(LMSHR_DOOR_SIZE); - if (!buf) + if ((arg = lmshrd_door_enter()) == NULL) return (NERR_InternalError); - enc_ctx = smb_dr_encode_start(buf, LMSHR_DOOR_SIZE); - smb_dr_put_uint32(enc_ctx, opcode); + enc_ctx = smb_dr_encode_start(arg->data_ptr, LMSHR_DOOR_SIZE); + smb_dr_put_uint32(enc_ctx, LMSHR_DOOR_CLOSE_ITERATOR); smb_dr_put_lmshr_iterator(enc_ctx, iterator); - if ((status = smb_dr_encode_finish(enc_ctx, &used)) != 0) { - syslog(LOG_ERR, "%s: Encode error %s", - lmshrd_desc[opcode], strerror(status)); - (void) free(buf); + + rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size); + if (rc != 0) { + lmshrd_door_exit(arg, "encode error"); return (NERR_InternalError); } - arg.data_ptr = buf; - arg.data_size = used; - arg.desc_ptr = NULL; - arg.desc_num = 0; - arg.rbuf = buf; - arg.rsize = LMSHR_DOOR_SIZE; - - if (door_call(lmshrd_fildes, &arg) < 0) { - syslog(LOG_DEBUG, "%s: Door call failed %s", - lmshrd_desc[opcode], strerror(errno)); - (void) free(buf); - lmshrd_fildes = -1; + if (door_call(lmshrd_fildes, arg) < 0) { + lmshrd_door_exit(arg, "door call error"); + lmshrd_door_close(); return (NERR_InternalError); } - dec_ctx = smb_dr_decode_start(arg.data_ptr, arg.data_size); - if (lmshrd_door_check_srv_status(opcode, dec_ctx) != 0) { - (void) free(buf); + dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size); + if (lmshrd_door_check_status(dec_ctx) != 0) { + (void) smb_dr_decode_finish(dec_ctx); + lmshrd_door_exit(arg, "decode error"); return (NERR_InternalError); } - if ((status = smb_dr_decode_finish(dec_ctx)) != 0) { - syslog(LOG_ERR, "%s: Decode error %s", - lmshrd_desc[opcode], strerror(status)); - (void) free(buf); + if (smb_dr_decode_finish(dec_ctx) != 0) { + lmshrd_door_exit(arg, "decode error"); return (NERR_InternalError); } - (void) free(buf); + lmshrd_door_exit(arg, NULL); return (NERR_Success); } DWORD lmshrd_iterate(uint64_t iterator, lmshare_info_t *si) { - door_arg_t arg; - char *buf; - unsigned int used; + door_arg_t *arg; smb_dr_ctx_t *dec_ctx; smb_dr_ctx_t *enc_ctx; - unsigned int status = 0; - int opcode = LMSHR_DOOR_ITERATE; + int rc; - if (lmshrd_door_open(opcode) == -1) - return (NERR_InternalError); - - buf = malloc(LMSHR_DOOR_SIZE); - if (!buf) + if ((arg = lmshrd_door_enter()) == NULL) return (NERR_InternalError); bzero(si, sizeof (lmshare_info_t)); - enc_ctx = smb_dr_encode_start(buf, LMSHR_DOOR_SIZE); - smb_dr_put_uint32(enc_ctx, opcode); + enc_ctx = smb_dr_encode_start(arg->data_ptr, LMSHR_DOOR_SIZE); + smb_dr_put_uint32(enc_ctx, LMSHR_DOOR_ITERATE); smb_dr_put_lmshr_iterator(enc_ctx, iterator); - if ((status = smb_dr_encode_finish(enc_ctx, &used)) != 0) { - syslog(LOG_ERR, "%s: Encode error %s", - lmshrd_desc[opcode], strerror(status)); - (void) free(buf); + + rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size); + if (rc != 0) { + lmshrd_door_exit(arg, "encode error"); return (NERR_InternalError); } - arg.data_ptr = buf; - arg.data_size = used; - arg.desc_ptr = NULL; - arg.desc_num = 0; - arg.rbuf = buf; - arg.rsize = LMSHR_DOOR_SIZE; - - if (door_call(lmshrd_fildes, &arg) < 0) { - syslog(LOG_DEBUG, "%s: Door call failed %s", - lmshrd_desc[opcode], strerror(errno)); - (void) free(buf); - lmshrd_fildes = -1; + if (door_call(lmshrd_fildes, arg) < 0) { + lmshrd_door_exit(arg, "door call error"); + lmshrd_door_close(); return (NERR_InternalError); } - dec_ctx = smb_dr_decode_start(arg.data_ptr, arg.data_size); - if (lmshrd_door_check_srv_status(opcode, dec_ctx) != 0) { - (void) free(buf); + dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size); + if (lmshrd_door_check_status(dec_ctx) != 0) { + (void) smb_dr_decode_finish(dec_ctx); + lmshrd_door_exit(arg, "decode error"); return (NERR_InternalError); } smb_dr_get_lmshare(dec_ctx, si); - if ((status = smb_dr_decode_finish(dec_ctx)) != 0) { - syslog(LOG_ERR, "%s: Decode error %s", - lmshrd_desc[opcode], strerror(status)); - (void) free(buf); + if (smb_dr_decode_finish(dec_ctx) != 0) { + lmshrd_door_exit(arg, "decode error"); return (NERR_InternalError); } - (void) free(buf); + lmshrd_door_exit(arg, NULL); return (NERR_Success); } DWORD lmshrd_list(int offset, lmshare_list_t *list) { - door_arg_t arg; - char *buf; - unsigned int used; + door_arg_t *arg; smb_dr_ctx_t *dec_ctx; smb_dr_ctx_t *enc_ctx; - int status; DWORD rc; - int opcode = LMSHR_DOOR_LIST; - if (lmshrd_door_open(opcode) == -1) + if ((arg = lmshrd_door_enter()) == NULL) return (NERR_InternalError); - buf = malloc(LMSHR_DOOR_SIZE); - - if (!buf) - return (NERR_InternalError); - - enc_ctx = smb_dr_encode_start(buf, LMSHR_DOOR_SIZE); - smb_dr_put_uint32(enc_ctx, opcode); + enc_ctx = smb_dr_encode_start(arg->data_ptr, LMSHR_DOOR_SIZE); + smb_dr_put_uint32(enc_ctx, LMSHR_DOOR_LIST); smb_dr_put_int32(enc_ctx, offset); - if ((status = smb_dr_encode_finish(enc_ctx, &used)) != 0) { - syslog(LOG_ERR, "%s: Encode error %s", - lmshrd_desc[opcode], strerror(status)); - (void) free(buf); + rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size); + if (rc != 0) { + lmshrd_door_exit(arg, "encode error"); return (NERR_InternalError); } - arg.data_ptr = buf; - arg.data_size = used; - arg.desc_ptr = NULL; - arg.desc_num = 0; - arg.rbuf = buf; - arg.rsize = LMSHR_DOOR_SIZE; - - if (door_call(lmshrd_fildes, &arg) < 0) { - syslog(LOG_DEBUG, "%s: Door call failed %s", - lmshrd_desc[opcode], strerror(errno)); - (void) free(buf); - lmshrd_fildes = -1; + if (door_call(lmshrd_fildes, arg) < 0) { + lmshrd_door_exit(arg, "door call error"); + lmshrd_door_close(); return (NERR_InternalError); } - dec_ctx = smb_dr_decode_start(arg.data_ptr, arg.data_size); - if (lmshrd_door_check_srv_status(opcode, dec_ctx) != 0) { - (void) free(buf); + dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size); + if (lmshrd_door_check_status(dec_ctx) != 0) { + (void) smb_dr_decode_finish(dec_ctx); + lmshrd_door_exit(arg, "decode error"); return (NERR_InternalError); } rc = smb_dr_get_uint32(dec_ctx); smb_dr_get_lmshr_list(dec_ctx, list); - if ((status = smb_dr_decode_finish(dec_ctx)) != 0) { - syslog(LOG_ERR, "%s: Decode error %s", - lmshrd_desc[opcode], strerror(status)); - (void) free(buf); + if (smb_dr_decode_finish(dec_ctx) != 0) { + lmshrd_door_exit(arg, "decode error"); return (NERR_InternalError); } - (void) free(buf); - + lmshrd_door_exit(arg, NULL); return (rc); } int lmshrd_num_shares(void) { - door_arg_t arg; - char *buf; - unsigned int used; + door_arg_t *arg; smb_dr_ctx_t *dec_ctx; smb_dr_ctx_t *enc_ctx; - unsigned int status = 0; DWORD num_shares; - int opcode = LMSHR_DOOR_NUM_SHARES; + int rc; - if (lmshrd_door_open(opcode) == -1) + if ((arg = lmshrd_door_enter()) == NULL) return (-1); - buf = malloc(LMSHR_DOOR_SIZE); - if (!buf) - return (-1); - - enc_ctx = smb_dr_encode_start(buf, LMSHR_DOOR_SIZE); + enc_ctx = smb_dr_encode_start(arg->data_ptr, LMSHR_DOOR_SIZE); smb_dr_put_uint32(enc_ctx, LMSHR_DOOR_NUM_SHARES); - if ((status = smb_dr_encode_finish(enc_ctx, &used)) != 0) { - syslog(LOG_ERR, "%s: Encode error %s", - lmshrd_desc[opcode], strerror(status)); - (void) free(buf); + + rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size); + if (rc != 0) { + lmshrd_door_exit(arg, "encode error"); return (-1); } - arg.data_ptr = buf; - arg.data_size = used; - arg.desc_ptr = NULL; - arg.desc_num = 0; - arg.rbuf = buf; - arg.rsize = LMSHR_DOOR_SIZE; - - if (door_call(lmshrd_fildes, &arg) < 0) { - syslog(LOG_DEBUG, "%s: Door call failed %s", - lmshrd_desc[opcode], strerror(errno)); - (void) free(buf); - lmshrd_fildes = -1; + if (door_call(lmshrd_fildes, arg) < 0) { + lmshrd_door_exit(arg, "door call error"); + lmshrd_door_close(); return (-1); } - dec_ctx = smb_dr_decode_start(arg.data_ptr, arg.data_size); - if (lmshrd_door_check_srv_status(opcode, dec_ctx) != 0) { - (void) free(buf); + dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size); + if (lmshrd_door_check_status(dec_ctx) != 0) { + (void) smb_dr_decode_finish(dec_ctx); + lmshrd_door_exit(arg, "decode error"); return (-1); } num_shares = smb_dr_get_uint32(dec_ctx); - if ((status = smb_dr_decode_finish(dec_ctx)) != 0) { - syslog(LOG_ERR, "%s: Decode error %s", - lmshrd_desc[opcode], strerror(status)); - (void) free(buf); + if (smb_dr_decode_finish(dec_ctx) != 0) { + lmshrd_door_exit(arg, "decode error"); return (-1); } - (void) free(buf); + lmshrd_door_exit(arg, NULL); return (num_shares); } DWORD lmshrd_delete(char *share_name) { - door_arg_t arg; - char *buf; - unsigned int used; + door_arg_t *arg; smb_dr_ctx_t *dec_ctx; smb_dr_ctx_t *enc_ctx; - int status; DWORD rc; - int opcode = LMSHR_DOOR_DELETE; - - if (lmshrd_door_open(opcode) == -1) - return (NERR_InternalError); - buf = malloc(LMSHR_DOOR_SIZE); - if (!buf) + if ((arg = lmshrd_door_enter()) == NULL) return (NERR_InternalError); - enc_ctx = smb_dr_encode_start(buf, LMSHR_DOOR_SIZE); + enc_ctx = smb_dr_encode_start(arg->data_ptr, LMSHR_DOOR_SIZE); smb_dr_put_uint32(enc_ctx, LMSHR_DOOR_DELETE); smb_dr_put_string(enc_ctx, share_name); - if ((status = smb_dr_encode_finish(enc_ctx, &used)) != 0) { - syslog(LOG_ERR, "%s: Encode error %s", - lmshrd_desc[opcode], strerror(status)); - (void) free(buf); + rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size); + if (rc != 0) { + lmshrd_door_exit(arg, "encode error"); return (NERR_InternalError); } - arg.data_ptr = buf; - arg.data_size = used; - arg.desc_ptr = NULL; - arg.desc_num = 0; - arg.rbuf = buf; - arg.rsize = LMSHR_DOOR_SIZE; - - if (door_call(lmshrd_fildes, &arg) < 0) { - syslog(LOG_DEBUG, "%s: Door call failed %s", - lmshrd_desc[opcode], strerror(errno)); - (void) free(buf); - lmshrd_fildes = -1; + if (door_call(lmshrd_fildes, arg) < 0) { + lmshrd_door_exit(arg, "door call error"); + lmshrd_door_close(); return (NERR_InternalError); } - dec_ctx = smb_dr_decode_start(arg.data_ptr, arg.data_size); - if (lmshrd_door_check_srv_status(opcode, dec_ctx) != 0) { - (void) free(buf); + dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size); + if (lmshrd_door_check_status(dec_ctx) != 0) { + (void) smb_dr_decode_finish(dec_ctx); + lmshrd_door_exit(arg, "decode error"); return (NERR_InternalError); } rc = smb_dr_get_uint32(dec_ctx); - if ((status = smb_dr_decode_finish(dec_ctx)) != 0) { - syslog(LOG_ERR, "%s: Decode error %s", - lmshrd_desc[opcode], strerror(status)); - (void) free(buf); + if (smb_dr_decode_finish(dec_ctx) != 0) { + lmshrd_door_exit(arg, "decode error"); return (NERR_InternalError); } - (void) free(buf); + lmshrd_door_exit(arg, NULL); return (rc); } @@ -502,316 +450,223 @@ lmshrd_delete(char *share_name) DWORD lmshrd_rename(char *from, char *to) { - door_arg_t arg; - char *buf; - unsigned int used; + door_arg_t *arg; smb_dr_ctx_t *dec_ctx; smb_dr_ctx_t *enc_ctx; - int status; DWORD rc; - int opcode = LMSHR_DOOR_RENAME; - - if (lmshrd_door_open(opcode) == -1) - return (NERR_InternalError); - buf = malloc(LMSHR_DOOR_SIZE); - if (!buf) + if ((arg = lmshrd_door_enter()) == NULL) return (NERR_InternalError); - enc_ctx = smb_dr_encode_start(buf, LMSHR_DOOR_SIZE); + enc_ctx = smb_dr_encode_start(arg->data_ptr, LMSHR_DOOR_SIZE); smb_dr_put_uint32(enc_ctx, LMSHR_DOOR_RENAME); smb_dr_put_string(enc_ctx, from); smb_dr_put_string(enc_ctx, to); - if ((status = smb_dr_encode_finish(enc_ctx, &used)) != 0) { - syslog(LOG_ERR, "%s: Encode error %s", - lmshrd_desc[opcode], strerror(status)); - (void) free(buf); + rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size); + if (rc != 0) { + lmshrd_door_exit(arg, "encode error"); return (NERR_InternalError); } - arg.data_ptr = buf; - arg.data_size = used; - arg.desc_ptr = NULL; - arg.desc_num = 0; - arg.rbuf = buf; - arg.rsize = LMSHR_DOOR_SIZE; - - if (door_call(lmshrd_fildes, &arg) < 0) { - syslog(LOG_DEBUG, "%s: Door call failed %s", - lmshrd_desc[opcode], strerror(errno)); - (void) free(buf); - lmshrd_fildes = -1; + if (door_call(lmshrd_fildes, arg) < 0) { + lmshrd_door_exit(arg, "door call error"); + lmshrd_door_close(); return (NERR_InternalError); } - dec_ctx = smb_dr_decode_start(arg.data_ptr, arg.data_size); - if (lmshrd_door_check_srv_status(opcode, dec_ctx) != 0) { - (void) free(buf); + dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size); + if (lmshrd_door_check_status(dec_ctx) != 0) { + (void) smb_dr_decode_finish(dec_ctx); + lmshrd_door_exit(arg, "decode error"); return (NERR_InternalError); } rc = smb_dr_get_uint32(dec_ctx); - if ((status = smb_dr_decode_finish(dec_ctx)) != 0) { - syslog(LOG_ERR, "%s: Decode error %s", - lmshrd_desc[opcode], strerror(status)); - (void) free(buf); + if (smb_dr_decode_finish(dec_ctx) != 0) { + lmshrd_door_exit(arg, "decode error"); return (NERR_InternalError); } - (void) free(buf); + lmshrd_door_exit(arg, NULL); return (rc); } DWORD lmshrd_getinfo(char *share_name, lmshare_info_t *si) { - door_arg_t arg; - char *buf; - unsigned int used; + door_arg_t *arg; smb_dr_ctx_t *dec_ctx; smb_dr_ctx_t *enc_ctx; - int status; DWORD rc; - int opcode = LMSHR_DOOR_GETINFO; - - if (lmshrd_door_open(opcode) == -1) - return (NERR_InternalError); - buf = malloc(LMSHR_DOOR_SIZE); - if (!buf) + if ((arg = lmshrd_door_enter()) == NULL) return (NERR_InternalError); - enc_ctx = smb_dr_encode_start(buf, LMSHR_DOOR_SIZE); + enc_ctx = smb_dr_encode_start(arg->data_ptr, LMSHR_DOOR_SIZE); smb_dr_put_uint32(enc_ctx, LMSHR_DOOR_GETINFO); smb_dr_put_string(enc_ctx, share_name); - if ((status = smb_dr_encode_finish(enc_ctx, &used)) != 0) { - syslog(LOG_ERR, "%s: Encode error %s", - lmshrd_desc[opcode], strerror(status)); - (void) free(buf); + rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size); + if (rc != 0) { + lmshrd_door_exit(arg, "encode error"); return (NERR_InternalError); } - arg.data_ptr = buf; - arg.data_size = used; - arg.desc_ptr = NULL; - arg.desc_num = 0; - arg.rbuf = buf; - arg.rsize = LMSHR_DOOR_SIZE; - - if (door_call(lmshrd_fildes, &arg) < 0) { - syslog(LOG_DEBUG, "%s: Door call failed %s", - lmshrd_desc[opcode], strerror(errno)); - (void) free(buf); - lmshrd_fildes = -1; + if (door_call(lmshrd_fildes, arg) < 0) { + lmshrd_door_exit(arg, "door call error"); + lmshrd_door_close(); return (NERR_InternalError); } - dec_ctx = smb_dr_decode_start(arg.data_ptr, arg.data_size); - if (lmshrd_door_check_srv_status(opcode, dec_ctx) != 0) { - (void) free(buf); + dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size); + if (lmshrd_door_check_status(dec_ctx) != 0) { + (void) smb_dr_decode_finish(dec_ctx); + lmshrd_door_exit(arg, "decode error"); return (NERR_InternalError); } rc = smb_dr_get_uint32(dec_ctx); smb_dr_get_lmshare(dec_ctx, si); - if ((status = smb_dr_decode_finish(dec_ctx)) != 0) { - syslog(LOG_ERR, "%s: Decode error %s", - lmshrd_desc[opcode], strerror(status)); - (void) free(buf); + if (smb_dr_decode_finish(dec_ctx) != 0) { + lmshrd_door_exit(arg, "decode error"); return (NERR_InternalError); } - (void) free(buf); + lmshrd_door_exit(arg, NULL); return (rc); } DWORD lmshrd_add(lmshare_info_t *si) { - door_arg_t arg; - char *buf; - unsigned int used; + door_arg_t *arg; smb_dr_ctx_t *dec_ctx; smb_dr_ctx_t *enc_ctx; - int status; DWORD rc; - int opcode = LMSHR_DOOR_ADD; - if (lmshrd_door_open(opcode) == -1) + if ((arg = lmshrd_door_enter()) == NULL) return (NERR_InternalError); - buf = malloc(LMSHR_DOOR_SIZE); - if (!buf) - return (NERR_InternalError); - - enc_ctx = smb_dr_encode_start(buf, LMSHR_DOOR_SIZE); - smb_dr_put_uint32(enc_ctx, opcode); + enc_ctx = smb_dr_encode_start(arg->data_ptr, LMSHR_DOOR_SIZE); + smb_dr_put_uint32(enc_ctx, LMSHR_DOOR_ADD); smb_dr_put_lmshare(enc_ctx, si); - if ((status = smb_dr_encode_finish(enc_ctx, &used)) != 0) { - syslog(LOG_ERR, "%s: Encode error %s", - lmshrd_desc[opcode], strerror(status)); - (void) free(buf); + rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size); + if (rc != 0) { + lmshrd_door_exit(arg, "encode error"); return (NERR_InternalError); } - arg.data_ptr = buf; - arg.data_size = used; - arg.desc_ptr = NULL; - arg.desc_num = 0; - arg.rbuf = buf; - arg.rsize = LMSHR_DOOR_SIZE; - - if (door_call(lmshrd_fildes, &arg) < 0) { - syslog(LOG_DEBUG, "%s: Door call failed %s", - lmshrd_desc[opcode], strerror(errno)); - (void) free(buf); - lmshrd_fildes = -1; + if (door_call(lmshrd_fildes, arg) < 0) { + lmshrd_door_exit(arg, "door call error"); + lmshrd_door_close(); return (NERR_InternalError); } - dec_ctx = smb_dr_decode_start(arg.data_ptr, arg.data_size); - if (lmshrd_door_check_srv_status(opcode, dec_ctx) != 0) { - (void) free(buf); + dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size); + if (lmshrd_door_check_status(dec_ctx) != 0) { + (void) smb_dr_decode_finish(dec_ctx); + lmshrd_door_exit(arg, "decode error"); return (NERR_InternalError); } rc = smb_dr_get_uint32(dec_ctx); smb_dr_get_lmshare(dec_ctx, si); - if ((status = smb_dr_decode_finish(dec_ctx)) != 0) { - syslog(LOG_ERR, "%s: Decode error %s", - lmshrd_desc[opcode], strerror(status)); - (void) free(buf); + if (smb_dr_decode_finish(dec_ctx) != 0) { + lmshrd_door_exit(arg, "decode error"); return (NERR_InternalError); } - (void) free(buf); + lmshrd_door_exit(arg, NULL); return (rc); } DWORD lmshrd_setinfo(lmshare_info_t *si) { - door_arg_t arg; - char *buf; - unsigned int used; + door_arg_t *arg; smb_dr_ctx_t *dec_ctx; smb_dr_ctx_t *enc_ctx; - int status; DWORD rc; - int opcode = LMSHR_DOOR_SETINFO; - - if (lmshrd_door_open(opcode) == -1) - return (NERR_InternalError); - buf = malloc(LMSHR_DOOR_SIZE); - if (!buf) + if ((arg = lmshrd_door_enter()) == NULL) return (NERR_InternalError); - enc_ctx = smb_dr_encode_start(buf, LMSHR_DOOR_SIZE); - smb_dr_put_uint32(enc_ctx, opcode); + enc_ctx = smb_dr_encode_start(arg->data_ptr, LMSHR_DOOR_SIZE); + smb_dr_put_uint32(enc_ctx, LMSHR_DOOR_SETINFO); smb_dr_put_lmshare(enc_ctx, si); - if ((status = smb_dr_encode_finish(enc_ctx, &used)) != 0) { - syslog(LOG_ERR, "%s: Encode error %s", - lmshrd_desc[opcode], strerror(status)); - (void) free(buf); + rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size); + if (rc != 0) { + lmshrd_door_exit(arg, "encode error"); return (NERR_InternalError); } - arg.data_ptr = buf; - arg.data_size = used; - arg.desc_ptr = NULL; - arg.desc_num = 0; - arg.rbuf = buf; - arg.rsize = LMSHR_DOOR_SIZE; - - if (door_call(lmshrd_fildes, &arg) < 0) { - syslog(LOG_DEBUG, "%s: Door call failed %s", - lmshrd_desc[opcode], strerror(errno)); - (void) free(buf); - lmshrd_fildes = -1; + if (door_call(lmshrd_fildes, arg) < 0) { + lmshrd_door_exit(arg, "door call error"); + lmshrd_door_close(); return (NERR_InternalError); } - dec_ctx = smb_dr_decode_start(arg.data_ptr, arg.data_size); - if (lmshrd_door_check_srv_status(opcode, dec_ctx) != 0) { - (void) free(buf); + dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size); + if (lmshrd_door_check_status(dec_ctx) != 0) { + (void) smb_dr_decode_finish(dec_ctx); + lmshrd_door_exit(arg, "decode error"); return (NERR_InternalError); } rc = smb_dr_get_uint32(dec_ctx); - if ((status = smb_dr_decode_finish(dec_ctx)) != 0) { - syslog(LOG_ERR, "%s: Decode error %s", - lmshrd_desc[opcode], strerror(status)); - (void) free(buf); + if (smb_dr_decode_finish(dec_ctx) != 0) { + lmshrd_door_exit(arg, "decode error"); return (NERR_InternalError); } - (void) free(buf); + lmshrd_door_exit(arg, NULL); return (rc); } static int lmshrd_check(char *share_name, int opcode) { - door_arg_t arg; - char *buf; - unsigned int used; + door_arg_t *arg; smb_dr_ctx_t *dec_ctx; smb_dr_ctx_t *enc_ctx; - int status, rc; + int rc; - if (lmshrd_door_open(opcode) == -1) + if ((arg = lmshrd_door_enter()) == NULL) return (NERR_InternalError); - buf = malloc(LMSHR_DOOR_SIZE); - if (!buf) - return (NERR_InternalError); - - enc_ctx = smb_dr_encode_start(buf, LMSHR_DOOR_SIZE); + enc_ctx = smb_dr_encode_start(arg->data_ptr, LMSHR_DOOR_SIZE); smb_dr_put_uint32(enc_ctx, opcode); smb_dr_put_string(enc_ctx, share_name); - if ((status = smb_dr_encode_finish(enc_ctx, &used)) != 0) { - syslog(LOG_ERR, "%s: Encode error %s", - lmshrd_desc[opcode], strerror(status)); - (void) free(buf); + rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size); + if (rc != 0) { + lmshrd_door_exit(arg, "encode error"); return (NERR_InternalError); } - arg.data_ptr = buf; - arg.data_size = used; - arg.desc_ptr = NULL; - arg.desc_num = 0; - arg.rbuf = buf; - arg.rsize = LMSHR_DOOR_SIZE; - - if (door_call(lmshrd_fildes, &arg) < 0) { - syslog(LOG_DEBUG, "%s: Door call failed %s", - lmshrd_desc[opcode], strerror(errno)); - (void) free(buf); - lmshrd_fildes = -1; + if (door_call(lmshrd_fildes, arg) < 0) { + lmshrd_door_exit(arg, "door call error"); + lmshrd_door_close(); return (NERR_InternalError); } - dec_ctx = smb_dr_decode_start(arg.data_ptr, arg.data_size); - if (lmshrd_door_check_srv_status(opcode, dec_ctx) != 0) { - (void) free(buf); + dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size); + if (lmshrd_door_check_status(dec_ctx) != 0) { + (void) smb_dr_decode_finish(dec_ctx); + lmshrd_door_exit(arg, "decode error"); return (NERR_InternalError); } rc = smb_dr_get_int32(dec_ctx); - if ((status = smb_dr_decode_finish(dec_ctx)) != 0) { - syslog(LOG_ERR, "%s: Decode error %s", - lmshrd_desc[opcode], strerror(status)); - (void) free(buf); + if (smb_dr_decode_finish(dec_ctx) != 0) { + lmshrd_door_exit(arg, "decode error"); return (NERR_InternalError); } - (void) free(buf); + lmshrd_door_exit(arg, NULL); return (rc); } @@ -850,102 +705,3 @@ lmshrd_is_dir(char *path) { return (lmshrd_check(path, LMSHR_DOOR_IS_DIR)); } - -static char * -lmshare_decode_type(unsigned int stype) -{ - switch (stype) { - case STYPE_DISKTREE: - return ("Disk"); - case STYPE_PRINTQ: - return ("Print Queue"); - case STYPE_DEVICE: - return ("Device"); - case STYPE_IPC: - return ("IPC"); - case STYPE_DFS: - return ("DFS"); - case STYPE_SPECIAL: - return ("Special"); - default: - return ("Unknown"); - }; -} - - -static void -lmshare_loginfo(FILE *fp, lmshare_info_t *si) -{ - if (!si) { - return; - } - - (void) fprintf(fp, "\n%s Information:\n", si->share_name); - (void) fprintf(fp, "\tFolder: %s\n", si->directory); - (void) fprintf(fp, "\tType: %s\n", lmshare_decode_type(si->stype)); - (void) fprintf(fp, "\tComment: %s\n", si->comment); - - (void) fprintf(fp, "\tStatus: %s\n", - ((si->mode & LMSHRM_TRANS) ? "Transient" : "Permanent")); - - (void) fprintf(fp, "\tContainer: %s\n", si->container); -} - -int -lmshrd_dump_hash(char *logfname) -{ - lmshare_info_t si; - uint64_t it; - FILE *fp; - - if ((logfname == 0) || (*logfname == 0)) - fp = stdout; - else { - fp = fopen(logfname, "w"); - if (fp == 0) { - syslog(LOG_WARNING, "LmshareDump [%s]:" - " cannot create logfile", logfname); - syslog(LOG_WARNING, "LmshareDump:" - " output will be written on screen"); - } - } - - it = lmshrd_open_iterator(LMSHRM_PERM); - if (it == NULL) { - syslog(LOG_ERR, "LmshareDump: resource shortage"); - if (fp && fp != stdout) { - (void) fclose(fp); - } - return (1); - } - - if (lmshrd_iterate(it, &si) != NERR_Success) { - syslog(LOG_ERR, "LmshareDump: Iterator iterate failed"); - if (fp && fp != stdout) { - (void) fclose(fp); - } - return (1); - } - while (*si.share_name != 0) { - lmshare_loginfo(fp, &si); - if (lmshrd_iterate(it, &si) != NERR_Success) { - syslog(LOG_ERR, "LmshareDump: Iterator iterate failed"); - if (fp && fp != stdout) { - (void) fclose(fp); - } - return (1); - } - } - - if (lmshrd_close_iterator(it) != NERR_Success) { - syslog(LOG_ERR, "LmshareDump: Iterator close failed"); - if (fp && fp != stdout) { - (void) fclose(fp); - } - return (1); - } - if (fp && fp != stdout) { - (void) fclose(fp); - } - return (0); -} diff --git a/usr/src/lib/libsqlite/Makefile.com b/usr/src/lib/libsqlite/Makefile.com index 49b42f553b..5bf5ebd84c 100644 --- a/usr/src/lib/libsqlite/Makefile.com +++ b/usr/src/lib/libsqlite/Makefile.com @@ -1,5 +1,5 @@ # -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -48,7 +48,8 @@ include $(SRC)/lib/Makefile.lib SRCDIR = ../src TOOLDIR = ../tool -LIBS = $(RELOC) $(LINTLIB) +$(DYNLIB) := LDLIBS += -lc +LIBS = $(RELOC) $(LINTLIB) $(DYNLIB) $(LINTLIB) := SRCS = $(LINTSRC) @@ -88,7 +89,7 @@ SRCS = \ MYCPPFLAGS = -D_REENTRANT -DTHREADSAFE=1 -DHAVE_USLEEP=1 -I. -I.. -I$(SRCDIR) CPPFLAGS += $(MYCPPFLAGS) -MAPFILE = ../mapfile-sqlite +MAPFILES = ../mapfile-sqlite # Header files used by all library source files. # @@ -198,11 +199,11 @@ $(OBJS) $(OBJS:%.o=%-native.o): $(HDR) native: $(NATIVERELOC) $(RELOC): objs .WAIT $(OBJS) - $(LD) -r $(MAPFILE:%=-M%) -o $(RELOC) $(OBJS) + $(LD) -r $(MAPFILES:%=-M%) -o $(RELOC) $(OBJS) $(CTFMERGE) -t -f -L VERSION -o $(RELOC) $(OBJS) $(NATIVERELOC): objs .WAIT $(OBJS:%.o=%-native.o) - $(LD) -r $(MAPFILE:%=-M%) -o $(NATIVERELOC) $(OBJS:%.o=%-native.o) + $(LD) -r $(MAPFILES:%=-M%) -o $(NATIVERELOC) $(OBJS:%.o=%-native.o) opcodes.h: $(SRCDIR)/vdbe.c @echo "Generating $@"; \ diff --git a/usr/src/lib/libsqlite/i386/Makefile b/usr/src/lib/libsqlite/i386/Makefile index 1cdf2c61ae..743fead699 100644 --- a/usr/src/lib/libsqlite/i386/Makefile +++ b/usr/src/lib/libsqlite/i386/Makefile @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -27,6 +27,6 @@ include ../Makefile.com -install: $(ROOTLIBDIR)/$(RELOC) +install: $(ROOTLIBDIR)/$(RELOC) $(ROOTLIBS) $(ROOTLINKS) $(ROOTLIBDIR)/$(RELOC): all diff --git a/usr/src/lib/libsqlite/sparc/Makefile b/usr/src/lib/libsqlite/sparc/Makefile index 1cdf2c61ae..743fead699 100644 --- a/usr/src/lib/libsqlite/sparc/Makefile +++ b/usr/src/lib/libsqlite/sparc/Makefile @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -27,6 +27,6 @@ include ../Makefile.com -install: $(ROOTLIBDIR)/$(RELOC) +install: $(ROOTLIBDIR)/$(RELOC) $(ROOTLIBS) $(ROOTLINKS) $(ROOTLIBDIR)/$(RELOC): all diff --git a/usr/src/lib/smbsrv/libmlrpc/Makefile.com b/usr/src/lib/smbsrv/libmlrpc/Makefile.com index cc5ba2923f..d4776174cd 100644 --- a/usr/src/lib/smbsrv/libmlrpc/Makefile.com +++ b/usr/src/lib/smbsrv/libmlrpc/Makefile.com @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -29,13 +29,13 @@ LIBRARY = libmlrpc.a VERS = .1 OBJS_COMMON = \ - mlndo.o \ - mlndr.o \ - mlrpc_client.o \ - mlrpc_encdec.o \ - mlrpc_heap.o \ - mlrpc_server.o \ - mlrpc_svc.o + ndr_client.o \ + ndr_heap.o \ + ndr_marshal.o \ + ndr_ops.o \ + ndr_process.o \ + ndr_server.o \ + ndr_svc.o NDLLIST = rpcpdu diff --git a/usr/src/lib/smbsrv/libmlrpc/common/mapfile-vers b/usr/src/lib/smbsrv/libmlrpc/common/mapfile-vers index 2f8fea95f3..5166d7d3d9 100644 --- a/usr/src/lib/smbsrv/libmlrpc/common/mapfile-vers +++ b/usr/src/lib/smbsrv/libmlrpc/common/mapfile-vers @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -48,6 +48,9 @@ SUNWprivate { mlrpc_process; mlrpc_register_service; mlrpc_release; + ndr_hdalloc; + ndr_hdfree; + ndr_hdlookup; ndr_mbstowcs; ndr_mbtowc; ndt__char; diff --git a/usr/src/lib/smbsrv/libmlrpc/common/mlrpc_client.c b/usr/src/lib/smbsrv/libmlrpc/common/ndr_client.c index 0f58231251..0f58231251 100644 --- a/usr/src/lib/smbsrv/libmlrpc/common/mlrpc_client.c +++ b/usr/src/lib/smbsrv/libmlrpc/common/ndr_client.c diff --git a/usr/src/lib/smbsrv/libmlrpc/common/mlrpc_heap.c b/usr/src/lib/smbsrv/libmlrpc/common/ndr_heap.c index 97a16ea010..97a16ea010 100644 --- a/usr/src/lib/smbsrv/libmlrpc/common/mlrpc_heap.c +++ b/usr/src/lib/smbsrv/libmlrpc/common/ndr_heap.c diff --git a/usr/src/lib/smbsrv/libmlrpc/common/mlrpc_encdec.c b/usr/src/lib/smbsrv/libmlrpc/common/ndr_marshal.c index 884683dfe4..884683dfe4 100644 --- a/usr/src/lib/smbsrv/libmlrpc/common/mlrpc_encdec.c +++ b/usr/src/lib/smbsrv/libmlrpc/common/ndr_marshal.c diff --git a/usr/src/lib/smbsrv/libmlrpc/common/mlndo.c b/usr/src/lib/smbsrv/libmlrpc/common/ndr_ops.c index c469223c4d..c469223c4d 100644 --- a/usr/src/lib/smbsrv/libmlrpc/common/mlndo.c +++ b/usr/src/lib/smbsrv/libmlrpc/common/ndr_ops.c diff --git a/usr/src/lib/smbsrv/libmlrpc/common/mlndr.c b/usr/src/lib/smbsrv/libmlrpc/common/ndr_process.c index e81225ede8..b64ada2955 100644 --- a/usr/src/lib/smbsrv/libmlrpc/common/mlndr.c +++ b/usr/src/lib/smbsrv/libmlrpc/common/ndr_process.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -1321,9 +1321,9 @@ mlndr_outer_string(struct ndr_reference *outer_ref) myref.inner_flags = NDR_F_NONE; /* - * Set up strlen_is so that we know what to - * expect later (see mlndr_s_wchar). + * Set up size_is and strlen_is for mlndr_s_wchar. */ + myref.size_is = size_is; myref.strlen_is = length_is; } @@ -1933,6 +1933,9 @@ mlndr_s_wchar(struct ndr_reference *encl_ref) if (count < 0) { return (0); } else if (count == 0) { + if (encl_ref->strlen_is != encl_ref->size_is) + break; + /* * If the input char is 0, mbtowc * returns 0 without setting wide_char. diff --git a/usr/src/lib/smbsrv/libmlrpc/common/mlrpc_server.c b/usr/src/lib/smbsrv/libmlrpc/common/ndr_server.c index 2f442937be..a1f203c09c 100644 --- a/usr/src/lib/smbsrv/libmlrpc/common/mlrpc_server.c +++ b/usr/src/lib/smbsrv/libmlrpc/common/ndr_server.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -70,8 +70,8 @@ static void mlrpc_reply_fault(struct mlrpc_xaction *, unsigned long); static int mlrpc_build_reply(struct mlrpc_xaction *); /* - * The is the RPC service server-side entry point. All MSRPC encoded - * messages should be passed through here. We use the same context + * This is the RPC service server-side entry point. All MSRPC encoded + * messages should be passed through here. We use the same context * structure as the client side but we don't need to set up the client * side info. */ @@ -98,6 +98,7 @@ mlrpc_process(int fid, smb_dr_user_ctx_t *user_ctx) return (NULL); bzero(mxa, sizeof (struct mlrpc_xaction)); + mxa->fid = fid; mxa->context = context; mxa->binding_list = context->binding; @@ -177,6 +178,8 @@ mlrpc_lookup(int fid) return (NULL); } + bzero(available->inpipe, sizeof (smb_pipe_t)); + bzero(available->outpipe, sizeof (smb_pipe_t)); available->fid = fid; available->inpipe->sp_pipeid = fid; available->outpipe->sp_pipeid = fid; @@ -205,6 +208,7 @@ mlrpc_release(int fid) context = &context_table[i]; if (context->fid == fid) { + ndr_hdclose(fid); free(context->inpipe); free(context->outpipe); bzero(context, sizeof (struct mlsvc_rpc_context)); @@ -267,8 +271,8 @@ mlrpc_s_bind(struct mlrpc_xaction *mxa) mlrpc_p_result_t *result; unsigned p_cont_id; struct mlrpc_binding *mbind; - mlrpc_uuid_t *as_uuid; - mlrpc_uuid_t *ts_uuid; + ndr_uuid_t *as_uuid; + ndr_uuid_t *ts_uuid; char as_buf[64]; char ts_buf[64]; int as_vers; @@ -414,8 +418,8 @@ mlrpc_s_alter_context(struct mlrpc_xaction *mxa) struct mlrpc_binding *mbind; struct mlrpc_service *msvc; unsigned p_cont_id; - mlrpc_uuid_t *as_uuid; - mlrpc_uuid_t *ts_uuid; + ndr_uuid_t *as_uuid; + ndr_uuid_t *ts_uuid; int as_vers; int ts_vers; mlrpc_port_any_t *sec_addr; diff --git a/usr/src/lib/smbsrv/libmlrpc/common/mlrpc_svc.c b/usr/src/lib/smbsrv/libmlrpc/common/ndr_svc.c index 771e54b7e4..1c051b560e 100644 --- a/usr/src/lib/smbsrv/libmlrpc/common/mlrpc_svc.c +++ b/usr/src/lib/smbsrv/libmlrpc/common/ndr_svc.c @@ -19,26 +19,44 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" +#include <synch.h> #include <stdio.h> +#include <unistd.h> #include <string.h> #include <strings.h> +#include <assert.h> #include <smbsrv/libsmb.h> #include <smbsrv/ndr.h> #include <smbsrv/mlrpc.h> +#include <smbsrv/ntsid.h> + +/* + * Global list of allocated handles. Handles are used in various + * server-side RPC functions: typically, issued when a service is + * opened and obsoleted when it is closed. Clients should treat + * handles as opaque data. + */ +static ndr_handle_t *ndr_handle_list; +static mutex_t ndr_handle_lock; + +/* + * Table of registered services. + */ #define NDL_MAX_SERVICES 32 -static struct mlrpc_service *mlrpc_services[NDL_MAX_SERVICES]; +static mlrpc_service_t *mlrpc_services[NDL_MAX_SERVICES]; + struct mlrpc_stub_table * -mlrpc_find_stub_in_svc(struct mlrpc_service *msvc, int opnum) +mlrpc_find_stub_in_svc(mlrpc_service_t *msvc, int opnum) { struct mlrpc_stub_table *ste; @@ -50,10 +68,10 @@ mlrpc_find_stub_in_svc(struct mlrpc_service *msvc, int opnum) return (NULL); } -struct mlrpc_service * +mlrpc_service_t * mlrpc_find_service_by_name(const char *name) { - struct mlrpc_service *msvc; + mlrpc_service_t *msvc; int i; for (i = 0; i < NDL_MAX_SERVICES; i++) { @@ -70,11 +88,11 @@ mlrpc_find_service_by_name(const char *name) return (NULL); } -struct mlrpc_service * -mlrpc_find_service_by_uuids(mlrpc_uuid_t *as_uuid, int as_vers, - mlrpc_uuid_t *ts_uuid, int ts_vers) +mlrpc_service_t * +mlrpc_find_service_by_uuids(ndr_uuid_t *as_uuid, int as_vers, + ndr_uuid_t *ts_uuid, int ts_vers) { - struct mlrpc_service *msvc; + mlrpc_service_t *msvc; char abstract_syntax[128]; char transfer_syntax[128]; int i; @@ -130,9 +148,9 @@ mlrpc_find_service_by_uuids(mlrpc_uuid_t *as_uuid, int as_vers, * -3 Table overflow */ int -mlrpc_register_service(struct mlrpc_service *msvc) +mlrpc_register_service(mlrpc_service_t *msvc) { - struct mlrpc_service *p; + mlrpc_service_t *p; int free_slot = -1; int i; @@ -158,7 +176,7 @@ mlrpc_register_service(struct mlrpc_service *msvc) } void -mlrpc_unregister_service(struct mlrpc_service *msvc) +mlrpc_unregister_service(mlrpc_service_t *msvc) { int i; @@ -171,7 +189,7 @@ mlrpc_unregister_service(struct mlrpc_service *msvc) int mlrpc_list_services(char *buffer, int bufsize) { - struct mlrpc_service *msvc; + mlrpc_service_t *msvc; smb_ctxbuf_t ctx; int i; @@ -187,8 +205,144 @@ mlrpc_list_services(char *buffer, int bufsize) return (smb_ctxbuf_len(&ctx)); } +/* + * Allocate a handle for use with the server-side RPC functions. + * The handle contains the machine SID and an incrementing counter, + * which should make each handle unique. + * + * An arbitrary caller context can be associated with the handle + * via data; it will not be dereferenced by the handle API. + * + * The uuid for the new handle is returned after it has been added + * to the global handle list. + */ +ndr_hdid_t * +ndr_hdalloc(const ndr_xa_t *xa, const void *data) +{ + static ndr_hdid_t uuid; + ndr_handle_t *hd; + nt_sid_t *sid; + + if ((hd = malloc(sizeof (ndr_handle_t))) == NULL) + return (NULL); + + if (uuid.data[1] == 0) { + if ((sid = nt_domain_local_sid()) == NULL) + return (NULL); + + uuid.data[0] = 0; + uuid.data[1] = 0; + uuid.data[2] = sid->SubAuthority[1]; + uuid.data[3] = sid->SubAuthority[2]; + uuid.data[4] = sid->SubAuthority[3]; + } + + ++uuid.data[1]; + + bcopy(&uuid, &hd->nh_id, sizeof (ndr_hdid_t)); + hd->nh_fid = xa->fid; + hd->nh_svc = xa->binding->service; + hd->nh_data = (void *)data; + + (void) mutex_lock(&ndr_handle_lock); + hd->nh_next = ndr_handle_list; + ndr_handle_list = hd; + (void) mutex_unlock(&ndr_handle_lock); + + return (&hd->nh_id); +} + +/* + * Remove a handle from the global list and free it. + */ +void +ndr_hdfree(const ndr_xa_t *xa, const ndr_hdid_t *id) +{ + mlrpc_service_t *svc = xa->binding->service; + ndr_handle_t *hd; + ndr_handle_t **pphd; + + assert(id); + + (void) mutex_lock(&ndr_handle_lock); + pphd = &ndr_handle_list; + + while (*pphd) { + hd = *pphd; + + if (bcmp(&hd->nh_id, id, sizeof (ndr_hdid_t)) == 0) { + if (hd->nh_svc == svc) { + *pphd = hd->nh_next; + free(hd); + } + break; + } + + pphd = &(*pphd)->nh_next; + } + + (void) mutex_unlock(&ndr_handle_lock); +} + +/* + * Lookup a handle by id. If the handle is in the list and it matches + * the specified service, a pointer to it is returned. Otherwise a null + * pointer is returned. + */ +ndr_handle_t * +ndr_hdlookup(const ndr_xa_t *xa, const ndr_hdid_t *id) +{ + mlrpc_service_t *svc = xa->binding->service; + ndr_handle_t *hd; + + assert(id); + (void) mutex_lock(&ndr_handle_lock); + hd = ndr_handle_list; + + while (hd) { + if (bcmp(&hd->nh_id, id, sizeof (ndr_hdid_t)) == 0) { + if (hd->nh_svc != svc) + break; + (void) mutex_unlock(&ndr_handle_lock); + return (hd); + } + + hd = hd->nh_next; + } + + (void) mutex_unlock(&ndr_handle_lock); + return (NULL); +} + +/* + * Called when a pipe is closed to release any associated handles. + */ +void +ndr_hdclose(int fid) +{ + ndr_handle_t *hd; + ndr_handle_t **pphd; + + (void) mutex_lock(&ndr_handle_lock); + pphd = &ndr_handle_list; + + while (*pphd) { + hd = *pphd; + + if (hd->nh_fid == fid) { + *pphd = hd->nh_next; + free(hd); + continue; + } + + pphd = &(*pphd)->nh_next; + } + + (void) mutex_unlock(&ndr_handle_lock); +} + void -mlrpc_uuid_to_str(mlrpc_uuid_t *uuid, char *str) +mlrpc_uuid_to_str(ndr_uuid_t *uuid, char *str) { (void) sprintf(str, "%08x-%04x-%04x-%02x%02x%02x%02x%02x%02x%02x%02x", uuid->data1, uuid->data2, uuid->data3, @@ -199,7 +353,7 @@ mlrpc_uuid_to_str(mlrpc_uuid_t *uuid, char *str) } int -mlrpc_str_to_uuid(char *str, mlrpc_uuid_t *uuid) +mlrpc_str_to_uuid(char *str, ndr_uuid_t *uuid) { char *p = str; char *q; diff --git a/usr/src/lib/smbsrv/libmlsvc/Makefile.com b/usr/src/lib/smbsrv/libmlsvc/Makefile.com index 60f0c4f66d..0b32262027 100644 --- a/usr/src/lib/smbsrv/libmlsvc/Makefile.com +++ b/usr/src/lib/smbsrv/libmlsvc/Makefile.com @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #pragma ident "%Z%%M% %I% %E% SMI" @@ -34,7 +34,6 @@ OBJS_COMMON = \ lsar_open.o \ mlsvc_client.o \ mlsvc_dssetup.o \ - mlsvc_handle.o \ mlsvc_init.o \ mlsvc_logr.o \ mlsvc_lsa.o \ diff --git a/usr/src/lib/smbsrv/libmlsvc/common/libmlsvc.h b/usr/src/lib/smbsrv/libmlsvc/common/libmlsvc.h index 71cc37af48..b77dde5340 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/libmlsvc.h +++ b/usr/src/lib/smbsrv/libmlsvc/common/libmlsvc.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -41,7 +41,8 @@ extern "C" { #endif extern int mlsvc_init(void); -extern int mlsvc_is_local_domain(const char *); +extern uint32_t mlsvc_lookup_name(char *, nt_sid_t **, uint16_t *); +extern uint32_t mlsvc_lookup_sid(nt_sid_t *, char **); extern DWORD lsa_query_primary_domain_info(void); extern DWORD lsa_query_account_domain_info(void); extern DWORD lsa_enum_trusted_domains(void); @@ -68,168 +69,6 @@ extern void smb_autohome_endent(void); extern smb_autohome_t *smb_autohome_getent(const char *name); extern smb_autohome_t *smb_autohome_lookup(const char *name); -/* - * Local groups - */ -#define NT_GROUP_FMRI_PREFIX "network/smb/group" - -typedef enum { - RWLOCK_NONE, - RWLOCK_WRITER, - RWLOCK_READER -} krwmode_t; - -typedef struct nt_group_data { - void *data; - int size; -} nt_group_data_t; - -/* - * IMPORTANT NOTE: - * If you change nt_group_member_t, nt_group_members_t, or nt_group_t - * structures, you MIGHT have to change following functions accordingly: - * nt_group_setfields - * nt_group_init_size - * nt_group_init - */ -typedef struct nt_group_member { - uint16_t info_size; /* size of the whole structure */ - uint16_t sid_name_use; /* type of the specified SID */ - char *account; /* Pointer to account name of member */ - nt_sid_t sid; /* Variable length */ -} nt_group_member_t; - -typedef struct nt_group_members { - uint32_t size; /* in bytes */ - uint32_t count; - nt_group_member_t list[ANY_SIZE_ARRAY]; -} nt_group_members_t; - -typedef struct nt_group { - time_t age; - nt_group_data_t info; - /* - * following fields point to a contigous block - * of memory that is read and written from/to DB - */ - uint32_t *attr; - uint16_t *sid_name_use; - char *name; - char *comment; - nt_sid_t *sid; - smb_privset_t *privileges; - nt_group_members_t *members; -} nt_group_t; - -typedef struct nt_group_iterator { - HT_ITERATOR *iterator; - int iteration; -} nt_group_iterator_t; - -extern int nt_group_num_groups(void); -extern uint32_t nt_group_add(char *, char *); -extern uint32_t nt_group_modify(char *, char *, char *); -extern uint32_t nt_group_delete(char *); -extern nt_group_t *nt_group_getinfo(char *, krwmode_t); -extern void nt_group_putinfo(nt_group_t *); - -extern int nt_group_getpriv(nt_group_t *, uint32_t); -extern uint32_t nt_group_setpriv(nt_group_t *, uint32_t, uint32_t); - -/* Member manipulation functions */ -extern int nt_group_is_member(nt_group_t *, nt_sid_t *); -extern uint32_t nt_group_del_member(nt_group_t *, void *, int); -extern uint32_t nt_group_add_member(nt_group_t *, nt_sid_t *, uint16_t, char *); -extern int nt_group_num_members(nt_group_t *); - -extern void nt_group_ht_lock(krwmode_t); -extern void nt_group_ht_unlock(void); - -extern nt_group_iterator_t *nt_group_open_iterator(void); -extern void nt_group_close_iterator(nt_group_iterator_t *); -extern nt_group_t *nt_group_iterate(nt_group_iterator_t *); - -extern int nt_group_cache_size(void); - -extern int nt_group_member_list(int offset, nt_group_t *grp, - ntgrp_member_list_t *rmembers); -extern void nt_group_list(int offset, char *pattern, ntgrp_list_t *list); - -extern uint32_t sam_init(void); - -extern uint32_t nt_group_add_member_byname(char *, char *); -extern uint32_t nt_group_del_member_byname(nt_group_t *, char *); -extern void nt_group_add_groupprivs(nt_group_t *, smb_privset_t *); - -extern uint32_t nt_groups_member_privs(nt_sid_t *, smb_privset_t *); -extern int nt_groups_member_ngroups(nt_sid_t *); -extern uint32_t nt_groups_member_groups(nt_sid_t *, smb_id_t *, int); -extern nt_group_t *nt_groups_lookup_rid(uint32_t); -extern int nt_groups_count(int); - -/* - * source for account name size is MSDN - */ -#define NT_GROUP_NAME_CHAR_MAX 32 -#define NT_GROUP_NAME_MAX (NT_GROUP_NAME_CHAR_MAX * 3 + 1) -#define NT_GROUP_USER_NAME_MAX (NT_GROUP_NAME_CHAR_MAX * 3 + 1) -#define NT_GROUP_MEMBER_NAME_MAX (NT_GROUP_NAME_CHAR_MAX * 3 + 1) -#define NT_GROUP_COMMENT_MAX 256 - -/* - * flags for count operation - */ -#define NT_GROUP_CNT_BUILTIN 1 -#define NT_GROUP_CNT_LOCAL 2 -#define NT_GROUP_CNT_ALL 3 - -/* - * flag to distinguish between add and modify - * operations. - */ -#define NT_GROUP_OP_CHANGE 1 -#define NT_GROUP_OP_SYNC 2 - -/* - * specify key type for deleting a member i.e. - * whether it's member's name or member's SID. - */ -#define NT_GROUP_KEY_SID 1 -#define NT_GROUP_KEY_NAME 2 - -/* Macro for walking members */ -#define NEXT_MEMBER(m) (nt_group_member_t *)((char *)(m) + (m)->info_size) - -/* - * When NT requests the security descriptor for a local file that - * doesn't already have a one, we generate one on-the-fly. The SD - * contains both user and group SIDs. The problem is that we need a - * way to distinguish a user SID from a group SID when NT performs a - * subsequent SID lookup to obtain the appropriate name to display. - * The following macros are used to map to and from an external - * representation so that we can tell the difference between UIDs - * and GIDs. The local UID/GID is shifted left and the LSB is used - * to distinguish the id type before it is inserted into the SID. - * We can then use this type identifier during lookup operations. - */ -#define SAM_MIN_RID 1000 -#define SAM_RT_ERROR -1 -#define SAM_RT_UNIX_UID 0 -#define SAM_RT_UNIX_GID 1 -#define SAM_RT_NT_UID 2 -#define SAM_RT_NT_GID 3 -#define SAM_RT_MASK 0x3 -#define SAM_RT_EVERYONE 4 -#define SAM_RT_UNKNOWN 5 - -#define SAM_RID_TYPE(rid) ((rid) & SAM_RT_MASK) -#define SAM_DECODE_RID(rid) (((rid) - SAM_MIN_RID) >> 2) -#define SAM_ENCODE_RID(type, id) ((((id) << 2) | type) + SAM_MIN_RID) -#define SAM_ENCODE_UXUID(id) SAM_ENCODE_RID(SAM_RT_UNIX_UID, id) -#define SAM_ENCODE_UXGID(id) SAM_ENCODE_RID(SAM_RT_UNIX_GID, id) -#define SAM_ENCODE_NTUID(id) SAM_ENCODE_RID(SAM_RT_NT_UID, id) -#define SAM_ENCODE_NTGID(id) SAM_ENCODE_RID(SAM_RT_NT_GID, id) - #ifdef __cplusplus } #endif diff --git a/usr/src/lib/smbsrv/libmlsvc/common/lmshare.c b/usr/src/lib/smbsrv/libmlsvc/common/lmshare.c index 5fb02b71f4..d131db4144 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/lmshare.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/lmshare.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -989,55 +989,6 @@ lmshare_setinfo(lmshare_info_t *si, int doshm) return (res); } -/* - * lmshare_decode_type - * - * Gets a SMB share type as an integer value and return - * a string name for it. - */ -static char * -lmshare_decode_type(uint_t stype) -{ - switch (stype) { - case STYPE_DISKTREE: - return ("Disk"); - case STYPE_PRINTQ: - return ("Print Queue"); - case STYPE_DEVICE: - return ("Device"); - case STYPE_IPC: - return ("IPC"); - case STYPE_DFS: - return ("DFS"); - case STYPE_SPECIAL: - return ("Special"); - default: - return ("Unknown"); - /* NOTREACHED */ - }; -} - -/* - * lmshare_loginfo - * - * Decodes and writes the information of the given - * share to the specified file. - */ -void -lmshare_loginfo(FILE *fp, lmshare_info_t *si) -{ - (void) fprintf(fp, "\n%s Information:\n", si->share_name); - (void) fprintf(fp, "\tFolder: %s\n", si->directory); - (void) fprintf(fp, "\tType: %s\n", - lmshare_decode_type((uint_t)si->stype)); - (void) fprintf(fp, "\tComment: %s\n", si->comment); - - (void) fprintf(fp, "\tStatus: %s\n", - ((si->mode & LMSHRM_TRANS) ? "Transient" : "Permanent")); - - (void) fprintf(fp, "\tContainer: %s\n", si->container); -} - DWORD lmshare_list(int offset, lmshare_list_t *list) { diff --git a/usr/src/lib/smbsrv/libmlsvc/common/lsalib.c b/usr/src/lib/smbsrv/libmlsvc/common/lsalib.c index 8e2effc333..4873d508cc 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/lsalib.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/lsalib.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -32,6 +32,8 @@ #include <strings.h> #include <unistd.h> #include <netdb.h> +#include <pwd.h> +#include <grp.h> #include <smbsrv/libsmb.h> #include <smbsrv/libsmbns.h> @@ -43,9 +45,111 @@ #include <smbsrv/ntsid.h> #include <smbsrv/smb_token.h> +/* + * Name Lookup modes + */ +#define MLSVC_LOOKUP_BUILTIN 1 +#define MLSVC_LOOKUP_LOCAL 2 +#define MLSVC_LOOKUP_DOMAIN 3 +#define MLSVC_LOOKUP_DOMLOC 4 + +static int lsa_lookup_mode(const char *, const char *); +static uint32_t lsa_lookup_name_builtin(char *, smb_userinfo_t *); +static uint32_t lsa_lookup_name_local(char *, char *, uint16_t, + smb_userinfo_t *); +static uint32_t lsa_lookup_name_lusr(char *, nt_sid_t **); +static uint32_t lsa_lookup_name_lgrp(char *, nt_sid_t **); +static uint32_t lsa_lookup_name_domain(char *, char *, char *, + smb_userinfo_t *); + +static uint32_t lsa_lookup_sid_builtin(nt_sid_t *, smb_userinfo_t *); +static uint32_t lsa_lookup_sid_local(nt_sid_t *, smb_userinfo_t *); +static uint32_t lsa_lookup_sid_domain(nt_sid_t *, smb_userinfo_t *); + static int lsa_list_accounts(mlsvc_handle_t *); /* + * lsa_lookup_name + * + * Lookup the given account and returns the account information + * in 'ainfo' + * + * If the name is a domain account, it may refer to a user, group or + * alias. If it is a local account, its type should be specified + * in the sid_type parameter. In case the account type is unknown + * sid_type should be set to SidTypeUnknown. + * + * account argument could be either [domain\\]name or [domain/]name. + * If domain is not specified and service is in domain mode then it + * first does a domain lookup and then a local lookup. + */ +uint32_t +lsa_lookup_name(char *server, char *account, uint16_t sid_type, + smb_userinfo_t *ainfo) +{ + nt_domain_t *dominfo; + int lookup_mode; + char *name; + char *domain; + uint32_t status = NT_STATUS_NONE_MAPPED; + + (void) strsubst(account, '\\', '/'); + name = strchr(account, '/'); + if (name) { + /* domain is specified */ + *name++ = '\0'; + domain = account; + } else { + name = account; + domain = NULL; + } + + lookup_mode = lsa_lookup_mode(domain, name); + + switch (lookup_mode) { + case MLSVC_LOOKUP_BUILTIN: + return (lsa_lookup_name_builtin(name, ainfo)); + + case MLSVC_LOOKUP_LOCAL: + return (lsa_lookup_name_local(domain, name, sid_type, ainfo)); + + case MLSVC_LOOKUP_DOMAIN: + return (lsa_lookup_name_domain(server, domain, name, ainfo)); + + default: + /* lookup the name in domain */ + dominfo = nt_domain_lookupbytype(NT_DOMAIN_PRIMARY); + if (dominfo == NULL) + return (NT_STATUS_INTERNAL_ERROR); + status = lsa_lookup_name_domain(server, dominfo->name, name, + ainfo); + if (status != NT_STATUS_NONE_MAPPED) + return (status); + + mlsvc_release_user_info(ainfo); + /* lookup the name locally */ + status = lsa_lookup_name_local(domain, name, sid_type, ainfo); + } + + return (status); +} + +uint32_t +lsa_lookup_sid(nt_sid_t *sid, smb_userinfo_t *ainfo) +{ + if (!nt_sid_is_valid(sid)) + return (NT_STATUS_INVALID_SID); + + if (nt_sid_is_local(sid)) + return (lsa_lookup_sid_local(sid, ainfo)); + + if (nt_builtin_lookup_sid(sid, NULL)) + return (lsa_lookup_sid_builtin(sid, ainfo)); + + return (lsa_lookup_sid_domain(sid, ainfo)); +} + +/* * lsa_query_primary_domain_info * * Obtains the primary domain SID and name from the specified server @@ -138,174 +242,115 @@ lsa_enum_trusted_domains(void) } /* - * lsa_test_lookup - * - * Test routine for lsa_lookup_name and lsa_lookup_sid. - */ -void -lsa_test_lookup(char *name) -{ - smb_userinfo_t *user_info; - nt_sid_t *sid; - DWORD status; - smb_ntdomain_t *di; - - if ((di = smb_getdomaininfo(0)) == 0) - return; - - user_info = mlsvc_alloc_user_info(); - - if (lsa_lookup_builtin_name(name, user_info) != 0) { - status = lsa_lookup_name(di->server, di->domain, name, - user_info); - - if (status == 0) { - sid = nt_sid_splice(user_info->domain_sid, - user_info->rid); - - (void) lsa_lookup_sid(sid, user_info); - free(sid); - } - } - - mlsvc_free_user_info(user_info); -} - -/* - * lsa_lookup_builtin_name + * lsa_lookup_name_builtin * * lookup builtin account table to see if account_name is * there. If it is there, set sid_name_use, domain_sid, * domain_name, and rid fields of the passed user_info - * structure and return 0. If lookup fails return 1. + * structure. */ -int -lsa_lookup_builtin_name(char *account_name, smb_userinfo_t *user_info) +static uint32_t +lsa_lookup_name_builtin(char *account_name, smb_userinfo_t *user_info) { char *domain; int res; - user_info->domain_sid = nt_builtin_lookup_name(account_name, + user_info->user_sid = nt_builtin_lookup_name(account_name, &user_info->sid_name_use); - if (user_info->domain_sid == 0) - return (1); + if (user_info->user_sid == NULL) + return (NT_STATUS_NONE_MAPPED); + user_info->domain_sid = nt_sid_dup(user_info->user_sid); res = nt_sid_split(user_info->domain_sid, &user_info->rid); if (res < 0) - return (1); + return (NT_STATUS_INTERNAL_ERROR); domain = nt_builtin_lookup_domain(account_name); if (domain) { user_info->domain_name = strdup(domain); - return (0); + return (NT_STATUS_SUCCESS); } - return (1); + return (NT_STATUS_INTERNAL_ERROR); } /* - * lsa_lookup_local_sam + * lsa_lookup_name_local * - * lookup for the given account name in the local SAM database. - * Returns 0 on success. If lookup fails return 1. - */ -int -lsa_lookup_local_sam(char *domain, char *account_name, - smb_userinfo_t *user_info) -{ - nt_group_t *grp; - - if (*domain == '\0' || *account_name == '\0') - return (1); - - grp = nt_group_getinfo(account_name, RWLOCK_READER); - if (grp == 0) - return (1); - - user_info->sid_name_use = *grp->sid_name_use; - user_info->domain_sid = nt_sid_dup(grp->sid); - nt_group_putinfo(grp); - - if (user_info->domain_sid == 0) - return (1); - - (void) nt_sid_split(user_info->domain_sid, &user_info->rid); - user_info->domain_name = strdup(domain); - - if (user_info->domain_name == 0) { - free(user_info->domain_sid); - user_info->domain_sid = 0; - return (1); - } - - return (0); -} - -/* - * lsa_lookup_local + * Obtains the infomation for the given local account name if it + * can be found. The type of account is specified by sid_type, + * which can be of user, group or unknown type. If the caller + * doesn't know whether the name is a user or group name then + * SidTypeUnknown should be passed, in which case this + * function first tries to find a user and then a group match. * - * if given account name has domain part, check to see if - * it matches with host name or any of host's primary addresses. - * if any match found first lookup in builtin accounts table and - * then in local SAM table. - * - * if account name doesn't have domain part, first do local lookups - * if nothing is found return 1. This means that caller function should - * do domain lookup. - * if any error happened return -1, if name is found return 0. + * CAVEAT: if there are both a user and a group account with + * the same name, user SID will always be returned. */ -int -lsa_lookup_local(char *name, smb_userinfo_t *user_info) +static uint32_t +lsa_lookup_name_local(char *domain, char *name, uint16_t sid_type, + smb_userinfo_t *ainfo) { char hostname[MAXHOSTNAMELEN]; - int res = 0; - int local_lookup = 0; - char *tmp; - net_cfg_t cfg; - uint32_t addr; - - if (smb_gethostname(hostname, MAXHOSTNAMELEN, 1) != 0) - return (-1); - - tmp = strchr(name, '\\'); - if (tmp != 0) { - *tmp = 0; - if (strcasecmp(name, hostname) == 0) - local_lookup = 1; - - if (!local_lookup) { - addr = inet_addr(name); - if (smb_nic_get_byip(addr, &cfg) != NULL) { - local_lookup = 1; - } - } - - if (!local_lookup) { - /* do domain lookup */ - *tmp = '\\'; - return (1); - } - - name = tmp + 1; - local_lookup = 1; + nt_sid_t *sid; + uint32_t status; + + switch (sid_type) { + case SidTypeUser: + status = lsa_lookup_name_lusr(name, &sid); + if (status != NT_STATUS_SUCCESS) + return (status); + break; + + case SidTypeGroup: + case SidTypeAlias: + status = lsa_lookup_name_lgrp(name, &sid); + if (status != NT_STATUS_SUCCESS) + return (status); + break; + + case SidTypeUnknown: + sid_type = SidTypeUser; + status = lsa_lookup_name_lusr(name, &sid); + if (status == NT_STATUS_SUCCESS) + break; + + if (status == NT_STATUS_NONE_MAPPED) + return (status); + + sid_type = SidTypeAlias; + status = lsa_lookup_name_lgrp(name, &sid); + if (status != NT_STATUS_SUCCESS) + return (status); + break; + + default: + return (NT_STATUS_INVALID_PARAMETER); } - res = lsa_lookup_builtin_name(name, user_info); - if (res != 0) - res = lsa_lookup_local_sam(hostname, name, user_info); - - if (res == 0) - return (0); + ainfo->sid_name_use = sid_type; + ainfo->user_sid = sid; + ainfo->domain_sid = nt_sid_dup(sid); + if (ainfo->domain_sid == NULL) + return (NT_STATUS_NO_MEMORY); + + (void) nt_sid_split(ainfo->domain_sid, &ainfo->rid); + if ((domain == NULL) || (*domain == '\0')) { + (void) smb_getnetbiosname(hostname, sizeof (hostname)); + ainfo->domain_name = strdup(hostname); + } else { + ainfo->domain_name = strdup(domain); + } - if (local_lookup) - return (-1); + if (ainfo->domain_name == NULL) + return (NT_STATUS_NO_MEMORY); - return (1); + return (NT_STATUS_SUCCESS); } /* - * lsa_lookup_name + * lsa_lookup_name_domain * * Lookup a name on the specified server (domain controller) and obtain * the appropriate SID. The information is returned in the user_info @@ -314,41 +359,16 @@ lsa_lookup_local(char *name, smb_userinfo_t *user_info) * type of SID. If the name is the domain name, this function will be * identical to lsa_domain_info. Otherwise the rid and name fields will * also be valid. On failure sid_name_use will be set to SidTypeUnknown. - * - * On success 0 is returned. Otherwise a -ve error code. - */ -int lsa_lookup_name(char *server, char *domain, char *account_name, - smb_userinfo_t *user_info) -{ - mlsvc_handle_t domain_handle; - int rc; - char *user = smbrdr_ipc_get_user(); - - rc = lsar_open(server, domain, user, &domain_handle); - if (rc != 0) - return (-1); - - rc = lsar_lookup_names(&domain_handle, account_name, user_info); - - (void) lsar_close(&domain_handle); - return (rc); -} - -/* - * lsa_lookup_name2 - * - * Returns NT status codes. */ -DWORD lsa_lookup_name2(char *server, char *domain, char *account_name, +static uint32_t +lsa_lookup_name_domain(char *server, char *domain, char *account_name, smb_userinfo_t *user_info) { mlsvc_handle_t domain_handle; - DWORD status; - int rc; char *user = smbrdr_ipc_get_user(); + uint32_t status; - rc = lsar_open(server, domain, user, &domain_handle); - if (rc != 0) + if (lsar_open(server, domain, user, &domain_handle) != 0) return (NT_STATUS_INVALID_PARAMETER); status = lsar_lookup_names2(&domain_handle, account_name, user_info); @@ -357,76 +377,8 @@ DWORD lsa_lookup_name2(char *server, char *domain, char *account_name, * Not a Windows 2000 domain controller: * use the NT compatible call. */ - if (lsar_lookup_names(&domain_handle, account_name, - user_info) != 0) - status = NT_STATUS_NONE_MAPPED; - else - status = 0; - } - - (void) lsar_close(&domain_handle); - return (status); -} - -/* - * lsa_lookup_sid - * - * Lookup a SID on the specified server (domain controller) and obtain - * the appropriate name. The information is returned in the user_info - * structure. The caller is responsible for allocating and releasing - * this structure. On success sid_name_use will be set to indicate the - * type of SID. On failure sid_name_use will be set to SidTypeUnknown. - * - * On success 0 is returned. Otherwise a -ve error code. - */ -int -lsa_lookup_sid(nt_sid_t *sid, smb_userinfo_t *user_info) -{ - mlsvc_handle_t domain_handle; - int rc; - char *user = smbrdr_ipc_get_user(); - - rc = lsar_open(NULL, NULL, user, &domain_handle); - if (rc != 0) - return (-1); - - rc = lsar_lookup_sids(&domain_handle, - (struct mslsa_sid *)sid, user_info); - - (void) lsar_close(&domain_handle); - return (rc); -} - -/* - * lsa_lookup_sid2 - * - * Returns NT status codes. - */ -DWORD -lsa_lookup_sid2(nt_sid_t *sid, smb_userinfo_t *user_info) -{ - mlsvc_handle_t domain_handle; - DWORD status; - int rc; - char *user = smbrdr_ipc_get_user(); - - rc = lsar_open(NULL, NULL, user, &domain_handle); - if (rc != 0) - return (NT_STATUS_INVALID_PARAMETER); - - status = lsar_lookup_sids2(&domain_handle, - (struct mslsa_sid *)sid, user_info); - - if (status == NT_STATUS_REVISION_MISMATCH) { - /* - * Not a Windows 2000 domain controller: - * use the NT compatible call. - */ - if (lsar_lookup_sids(&domain_handle, (struct mslsa_sid *)sid, - user_info) != 0) - status = NT_STATUS_NONE_MAPPED; - else - status = 0; + status = lsar_lookup_names(&domain_handle, account_name, + user_info); } (void) lsar_close(&domain_handle); @@ -434,12 +386,12 @@ lsa_lookup_sid2(nt_sid_t *sid, smb_userinfo_t *user_info) } /* - * lsa_test_lookup2 + * lsa_test_lookup * - * Test routine for lsa_lookup_name2 and lsa_lookup_sid2. + * Test routine for lsa_lookup_name_domain and lsa_lookup_sid2. */ void -lsa_test_lookup2(char *name) +lsa_test_lookup(char *name) { smb_userinfo_t *user_info; nt_sid_t *sid; @@ -451,15 +403,15 @@ lsa_test_lookup2(char *name) user_info = mlsvc_alloc_user_info(); - if (lsa_lookup_builtin_name(name, user_info) != 0) { - status = lsa_lookup_name2(di->server, di->domain, name, + if (lsa_lookup_name_builtin(name, user_info) != 0) { + status = lsa_lookup_name_domain(di->server, di->domain, name, user_info); if (status == 0) { sid = nt_sid_splice(user_info->domain_sid, user_info->rid); - (void) lsa_lookup_sid2(sid, user_info); + (void) lsa_lookup_sid_domain(sid, user_info); free(sid); } } @@ -627,3 +579,177 @@ lsa_list_accounts(mlsvc_handle_t *domain_handle) mlsvc_free_user_info(user_info); return (0); } + +/* + * lsa_lookup_name_lusr + * + * Obtains the SID for the given local user name if it + * can be found. Upon successful return the allocated memory + * for the returned SID must be freed by the caller. + * + * Note that in domain mode this function might actually return + * a domain SID if local users are mapped to domain users. + */ +static uint32_t +lsa_lookup_name_lusr(char *name, nt_sid_t **sid) +{ + struct passwd *pw; + + if ((pw = getpwnam(name)) == NULL) + return (NT_STATUS_NO_SUCH_USER); + + if (smb_idmap_getsid(pw->pw_uid, SMB_IDMAP_USER, sid) != IDMAP_SUCCESS) + return (NT_STATUS_NONE_MAPPED); + + return (NT_STATUS_SUCCESS); +} + +/* + * lsa_lookup_name_lgrp + * + * Obtains the SID for the given local group name if it + * can be found. Upon successful return the allocated memory + * for the returned SID must be freed by the caller. + * + * Note that in domain mode this function might actually return + * a domain SID if local groups are mapped to domain groups. + */ +static uint32_t +lsa_lookup_name_lgrp(char *name, nt_sid_t **sid) +{ + struct group *gr; + + if ((gr = getgrnam(name)) == NULL) + return (NT_STATUS_NO_SUCH_ALIAS); + + if (smb_idmap_getsid(gr->gr_gid, SMB_IDMAP_GROUP, sid) != IDMAP_SUCCESS) + return (NT_STATUS_NONE_MAPPED); + + return (NT_STATUS_SUCCESS); +} + +static int +lsa_lookup_mode(const char *domain, const char *name) +{ + int lookup_mode; + + if (nt_builtin_lookup((char *)name)) + return (MLSVC_LOOKUP_BUILTIN); + + if (smb_config_get_secmode() == SMB_SECMODE_WORKGRP) + return (MLSVC_LOOKUP_LOCAL); + + if ((domain == NULL) || (*domain == '\0')) + return (MLSVC_LOOKUP_DOMLOC); + + if (mlsvc_is_local_domain(domain) == 1) + lookup_mode = MLSVC_LOOKUP_LOCAL; + else + lookup_mode = MLSVC_LOOKUP_DOMAIN; + + return (lookup_mode); +} + +static uint32_t +lsa_lookup_sid_local(nt_sid_t *sid, smb_userinfo_t *ainfo) +{ + char hostname[MAXHOSTNAMELEN]; + struct passwd *pw; + struct group *gr; + uid_t id; + int id_type; + + id_type = SMB_IDMAP_UNKNOWN; + if (smb_idmap_getid(sid, &id, &id_type) != IDMAP_SUCCESS) + return (NT_STATUS_NONE_MAPPED); + + switch (id_type) { + case SMB_IDMAP_USER: + ainfo->sid_name_use = SidTypeUser; + if ((pw = getpwuid(id)) == NULL) + return (NT_STATUS_NO_SUCH_USER); + + ainfo->name = strdup(pw->pw_name); + break; + + case SMB_IDMAP_GROUP: + ainfo->sid_name_use = SidTypeAlias; + if ((gr = getgrgid(id)) == NULL) + return (NT_STATUS_NO_SUCH_ALIAS); + + ainfo->name = strdup(gr->gr_name); + break; + + default: + return (NT_STATUS_NONE_MAPPED); + } + + if (ainfo->name == NULL) + return (NT_STATUS_NO_MEMORY); + + ainfo->domain_sid = nt_sid_dup(sid); + if (nt_sid_split(ainfo->domain_sid, &ainfo->rid) < 0) + return (NT_STATUS_INTERNAL_ERROR); + *hostname = '\0'; + (void) smb_getnetbiosname(hostname, MAXHOSTNAMELEN); + if ((ainfo->domain_name = strdup(hostname)) == NULL) + return (NT_STATUS_NO_MEMORY); + + return (NT_STATUS_SUCCESS); +} + +static uint32_t +lsa_lookup_sid_builtin(nt_sid_t *sid, smb_userinfo_t *ainfo) +{ + char *name; + WORD sid_name_use; + + if ((name = nt_builtin_lookup_sid(sid, &sid_name_use)) == NULL) + return (NT_STATUS_NONE_MAPPED); + + ainfo->sid_name_use = sid_name_use; + ainfo->name = strdup(name); + ainfo->domain_sid = nt_sid_dup(sid); + + if (ainfo->name == NULL || ainfo->domain_sid == NULL) + return (NT_STATUS_NO_MEMORY); + + if (sid_name_use != SidTypeDomain) + (void) nt_sid_split(ainfo->domain_sid, &ainfo->rid); + + if ((name = nt_builtin_lookup_domain(ainfo->name)) != NULL) + ainfo->domain_name = strdup(name); + else + ainfo->domain_name = strdup("UNKNOWN"); + + if (ainfo->domain_name == NULL) + return (NT_STATUS_NO_MEMORY); + + return (NT_STATUS_SUCCESS); +} + +static uint32_t +lsa_lookup_sid_domain(nt_sid_t *sid, smb_userinfo_t *ainfo) +{ + mlsvc_handle_t domain_handle; + char *user = smbrdr_ipc_get_user(); + uint32_t status; + + if (lsar_open(NULL, NULL, user, &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); + } + + (void) lsar_close(&domain_handle); + return (status); +} diff --git a/usr/src/lib/smbsrv/libmlsvc/common/lsar_lookup.c b/usr/src/lib/smbsrv/libmlsvc/common/lsar_lookup.c index 5216818cce..f8f21e08cc 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/lsar_lookup.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/lsar_lookup.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -175,15 +175,15 @@ lsar_query_info_policy(mlsvc_handle_t *lsa_handle, WORD infoClass) * If the lookup fails, the status will typically be * NT_STATUS_NONE_MAPPED. */ -int +uint32_t lsar_lookup_names(mlsvc_handle_t *lsa_handle, char *name, smb_userinfo_t *user_info) { struct mlsvc_rpc_context *context; mlrpc_heapref_t heap; int opnum; - int rc; int index; + uint32_t status; struct mslsa_LookupNames arg; size_t length; lookup_name_table_t name_table; @@ -192,7 +192,7 @@ lsar_lookup_names(mlsvc_handle_t *lsa_handle, char *name, char *p; if (lsa_handle == NULL || name == NULL || user_info == NULL) - return (-1); + return (NT_STATUS_INVALID_PARAMETER); bzero(user_info, sizeof (smb_userinfo_t)); user_info->sid_name_use = SidTypeUnknown; @@ -239,35 +239,39 @@ lsar_lookup_names(mlsvc_handle_t *lsa_handle, char *name, name_table.name[0].str = (unsigned char *)name; (void) mlsvc_rpc_init(&heap); - rc = mlsvc_rpc_call(context, opnum, &arg, &heap); - if (rc == 0) { - if (arg.status != 0) { - rc = -1; - } else if (arg.mapped_count == 0) { - rc = -1; + if (mlsvc_rpc_call(context, opnum, &arg, &heap) != 0) { + status = NT_STATUS_INVALID_PARAMETER; + } else if (arg.status != 0) { + mlsvc_rpc_report_status(opnum, arg.status); + status = NT_SC_VALUE(arg.status); + } else if (arg.mapped_count == 0) { + user_info->sid_name_use = SidTypeInvalid; + status = NT_STATUS_NONE_MAPPED; + } else { + rid_entry = &arg.translated_sids.rids[0]; + user_info->sid_name_use = rid_entry->sid_name_use; + user_info->rid = rid_entry->rid; + user_info->name = MEM_STRDUP("mlrpc", name); + + if ((index = rid_entry->domain_index) == -1) { + user_info->domain_sid = 0; + user_info->domain_name = 0; } else { - rid_entry = &arg.translated_sids.rids[0]; - user_info->sid_name_use = rid_entry->sid_name_use; - user_info->rid = rid_entry->rid; - user_info->name = MEM_STRDUP("mlrpc", name); - - if ((index = rid_entry->domain_index) == -1) { - user_info->domain_sid = 0; - user_info->domain_name = 0; - } else { - domain_entry = - &arg.domain_table->entries[index]; - user_info->domain_sid = nt_sid_dup( - (nt_sid_t *)domain_entry->domain_sid); - user_info->domain_name = MEM_STRDUP("mlrpc", - (const char *) - domain_entry->domain_name.str); - } + domain_entry = + &arg.domain_table->entries[index]; + user_info->domain_sid = nt_sid_dup( + (nt_sid_t *)domain_entry->domain_sid); + user_info->domain_name = MEM_STRDUP("mlrpc", + (const char *) + domain_entry->domain_name.str); + user_info->user_sid = nt_sid_splice( + user_info->domain_sid, user_info->rid); } + status = NT_STATUS_SUCCESS; } mlsvc_rpc_free(context, &heap); - return (rc); + return (status); } /* @@ -279,7 +283,7 @@ lsar_lookup_names(mlsvc_handle_t *lsa_handle, char *name, * 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. */ -int +uint32_t lsar_lookup_sids(mlsvc_handle_t *lsa_handle, struct mslsa_sid *sid, smb_userinfo_t *user_info) { @@ -290,11 +294,11 @@ lsar_lookup_sids(mlsvc_handle_t *lsa_handle, struct mslsa_sid *sid, struct mlsvc_rpc_context *context; mlrpc_heapref_t heap; int opnum; - int rc; int index; + uint32_t status; if (lsa_handle == NULL || sid == NULL || user_info == NULL) - return (-1); + return (NT_STATUS_INVALID_PARAMETER); context = lsa_handle->context; opnum = LSARPC_OPNUM_LookupSids; @@ -308,45 +312,48 @@ lsar_lookup_sids(mlsvc_handle_t *lsa_handle, struct mslsa_sid *sid, arg.lup_sid_table.entries = &sid_entry; (void) mlsvc_rpc_init(&heap); - rc = mlsvc_rpc_call(context, opnum, &arg, &heap); - if (rc == 0) { - if (arg.mapped_count == 0) { - user_info->sid_name_use = SidTypeInvalid; - rc = 1; - } else { - name_entry = &arg.name_table.entries[0]; - user_info->sid_name_use = name_entry->sid_name_use; + if (mlsvc_rpc_call(context, opnum, &arg, &heap) != 0) { + status = NT_STATUS_INVALID_PARAMETER; + } else if (arg.mapped_count == 0) { + user_info->sid_name_use = SidTypeInvalid; + status = NT_STATUS_NONE_MAPPED; + } else if (arg.status != 0) { + mlsvc_rpc_report_status(opnum, arg.status); + status = NT_SC_VALUE(arg.status); + } else { + name_entry = &arg.name_table.entries[0]; + user_info->sid_name_use = name_entry->sid_name_use; - if (user_info->sid_name_use == SidTypeUser || - user_info->sid_name_use == SidTypeGroup || - user_info->sid_name_use == SidTypeAlias) { + if (user_info->sid_name_use == SidTypeUser || + user_info->sid_name_use == SidTypeGroup || + user_info->sid_name_use == SidTypeAlias) { - user_info->rid = - sid->SubAuthority[sid->SubAuthCount - 1]; + user_info->rid = + sid->SubAuthority[sid->SubAuthCount - 1]; - user_info->name = MEM_STRDUP("mlrpc", - (const char *)name_entry->name.str); - } + user_info->name = MEM_STRDUP("mlrpc", + (const char *)name_entry->name.str); + } - if ((index = name_entry->domain_ix) == -1) { - user_info->domain_sid = 0; - user_info->domain_name = 0; - } else { - domain_entry = - &arg.domain_table->entries[index]; + if ((index = name_entry->domain_ix) == -1) { + user_info->domain_sid = 0; + user_info->domain_name = 0; + } else { + domain_entry = + &arg.domain_table->entries[index]; - user_info->domain_sid = nt_sid_dup( - (nt_sid_t *)domain_entry->domain_sid); + user_info->domain_sid = nt_sid_dup( + (nt_sid_t *)domain_entry->domain_sid); - user_info->domain_name = MEM_STRDUP("mlrpc", - (const char *) - domain_entry->domain_name.str); - } + user_info->domain_name = MEM_STRDUP("mlrpc", + (const char *) + domain_entry->domain_name.str); } + status = NT_STATUS_SUCCESS; } mlsvc_rpc_free(context, &heap); - return (rc); + return (status); } /* @@ -728,8 +735,6 @@ lsar_lookup_sids2(mlsvc_handle_t *lsa_handle, struct mslsa_sid *sid, mlsvc_rpc_report_status(opnum, arg.status); status = NT_SC_VALUE(arg.status); } else { - status = 0; - name_entry = &arg.name_table.entries[0]; user_info->sid_name_use = name_entry->sid_name_use; @@ -757,6 +762,7 @@ lsar_lookup_sids2(mlsvc_handle_t *lsa_handle, struct mslsa_sid *sid, user_info->domain_name = MEM_STRDUP("mlrpc", (char const *)domain_entry->domain_name.str); } + status = NT_STATUS_SUCCESS; } mlsvc_rpc_free(context, &heap); @@ -780,7 +786,7 @@ lsar_lookup_sids2(mlsvc_handle_t *lsa_handle, struct mslsa_sid *sid, * * It should be okay to lookup DOMAIN\Administrator in this function. */ -DWORD +uint32_t lsar_lookup_names2(mlsvc_handle_t *lsa_handle, char *name, smb_userinfo_t *user_info) { @@ -793,7 +799,7 @@ lsar_lookup_names2(mlsvc_handle_t *lsa_handle, char *name, lookup_name_table_t name_table; struct lsar_rid_entry2 *rid_entry; struct mslsa_domain_entry *domain_entry; - DWORD status; + uint32_t status; if (lsa_handle == NULL || name == NULL || user_info == NULL) return (NT_STATUS_INVALID_PARAMETER); @@ -831,8 +837,6 @@ lsar_lookup_names2(mlsvc_handle_t *lsa_handle, char *name, user_info->sid_name_use = SidTypeInvalid; status = NT_STATUS_NONE_MAPPED; } else { - status = 0; - rid_entry = &arg.translated_sids.rids[0]; user_info->sid_name_use = rid_entry->sid_name_use; user_info->rid = rid_entry->rid; @@ -849,7 +853,10 @@ lsar_lookup_names2(mlsvc_handle_t *lsa_handle, char *name, user_info->domain_name = MEM_STRDUP("mlrpc", (char const *)domain_entry->domain_name.str); + user_info->user_sid = nt_sid_splice( + user_info->domain_sid, user_info->rid); } + status = NT_STATUS_SUCCESS; } mlsvc_rpc_free(context, &heap); diff --git a/usr/src/lib/smbsrv/libmlsvc/common/mapfile-vers b/usr/src/lib/smbsrv/libmlsvc/common/mapfile-vers index a294b0ef2e..05608e27d6 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/mapfile-vers +++ b/usr/src/lib/smbsrv/libmlsvc/common/mapfile-vers @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # @@ -46,41 +46,13 @@ SUNWprivate { lmshare_setinfo; lmshare_start; lmshare_stop; - lsa_lookup_name2; - lsa_lookup_sid2; lsa_query_primary_domain_info; lsa_query_account_domain_info; lsa_enum_trusted_domains; mlsvc_init; - mlsvc_is_local_domain; mlsvc_join; - nt_group_add; - nt_group_add_groupprivs; - nt_group_add_member_byname; - nt_group_cache_size; - nt_group_close_iterator; - nt_group_delete; - nt_group_del_member_byname; - nt_group_getinfo; - nt_group_getpriv; - nt_group_ht_lock; - nt_group_ht_unlock; - nt_group_is_member; - nt_group_iterate; - nt_group_modify; - nt_group_num_groups; - nt_group_num_members; - nt_group_open_iterator; - nt_group_putinfo; - nt_groups_count; - nt_group_setpriv; - nt_groups_lookup_rid; - nt_groups_member_groups; - nt_groups_member_ngroups; - nt_groups_member_privs; - nt_group_list; - nt_group_member_list; - sam_init; + mlsvc_lookup_name; + mlsvc_lookup_sid; smb_logon; smb_token_destroy; smb_build_lmshare_info; diff --git a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_client.c b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_client.c index de20a8c934..25acdec4f2 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_client.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_client.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -193,7 +193,7 @@ mlsvc_xa_exchange(struct mlrpc_client *mcli, struct mlrpc_xaction *mxa) struct mlndr_stream *send_mlnds = &mxa->send_mlnds; int rc; - rc = smbrdr_rpc_transact(context->fid, + rc = smbrdr_transact(context->fid, (char *)send_mlnds->pdu_base_offset, send_mlnds->pdu_size, (char *)recv_mlnds->pdu_base_offset, recv_mlnds->pdu_max_size); @@ -228,7 +228,7 @@ mlsvc_xa_read(struct mlrpc_client *mcli, struct mlrpc_xaction *mxa) if ((len = (mlnds->pdu_max_size - mlnds->pdu_size)) < 0) return (-1); - rc = smbrdr_rpc_readx(context->fid, + rc = smbrdr_readx(context->fid, (char *)mlnds->pdu_base_offset + mlnds->pdu_size, len); if (rc < 0) diff --git a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_dssetup.c b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_dssetup.c index a20304afa8..659b184919 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_dssetup.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_dssetup.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -103,7 +103,7 @@ dssetup_DsRoleGetPrimaryDomainInfo(void *arg, struct mlrpc_xaction *mxa) } di = smb_getdomaininfo(0); - (void) smb_getdomainname(dns_domain, MAXHOSTNAMELEN); + (void) smb_getfqdomainname(dns_domain, MAXHOSTNAMELEN); if (di == NULL) { bzero(param, @@ -122,7 +122,7 @@ dssetup_DsRoleGetPrimaryDomainInfo(void *arg, struct mlrpc_xaction *mxa) (uint8_t *)MLRPC_HEAP_STRSAVE(mxa, dns_domain); param->ru.info1.forest = (uint8_t *)MLRPC_HEAP_STRSAVE(mxa, dns_domain); - bzero(¶m->ru.info1.domain_guid, sizeof (mlrpc_uuid_t)); + bzero(¶m->ru.info1.domain_guid, sizeof (ndr_uuid_t)); if (param->ru.info1.nt_domain == NULL || param->ru.info1.dns_domain == NULL || diff --git a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_handle.c b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_handle.c deleted file mode 100644 index a13b7346f5..0000000000 --- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_handle.c +++ /dev/null @@ -1,179 +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 2007 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -/* - * This module provides the handles used in the various server-side - * RPC functions. I don't think other systems care about the value in - * the handle. It should be treated as an opaque data block. Handles - * are issued when a service is opened and obsoleted when it is closed. - * We should check incoming RPC requests to ensure that the handle - * being used is associated with the particular service being accessed. - */ - -#include <strings.h> -#include <unistd.h> -#include <assert.h> - -#include <smbsrv/libsmb.h> -#include <smbsrv/mlsvc_util.h> -#include <smbsrv/ntsid.h> - -/* - * Each time a handle is allocated it is added to the global handle - * descriptor list because we need some way of identifying the - * interface and domain to which the handle was assigned when it is - * returned on a subsequent RPC. - */ -ms_handle_t mlsvc_handle; -ms_handle_desc_t *mlsvc_desc_list; - -/* - * mlsvc_get_handle - * - * This function returns a handle for use with the server-side RPC - * functions. Every time it is called it will increment the handle - * value and return a pointer to it. On NT, handle[0] always seems - * to be zero and handle[1] increments. The rest seems to be some - * sort of unique value so the local domain SID should do. - * - * The handle is added to the global handle descriptor list with the - * designated ifspec and key tag. - */ -ms_handle_t * -mlsvc_get_handle(ms_ifspec_t ifspec, char *key, DWORD discrim) -{ - ms_handle_desc_t *desc; - nt_sid_t *sid; - - if ((desc = malloc(sizeof (ms_handle_desc_t))) == NULL) - assert(desc); - - sid = nt_domain_local_sid(); - if (mlsvc_handle.handle[1] == 0) { - mlsvc_handle.handle[0] = 0; - mlsvc_handle.handle[1] = 0; - mlsvc_handle.handle[2] = sid->SubAuthority[1]; - mlsvc_handle.handle[3] = sid->SubAuthority[2]; - mlsvc_handle.handle[4] = sid->SubAuthority[3]; - } - - ++mlsvc_handle.handle[1]; - - bcopy(&mlsvc_handle, &desc->handle, sizeof (ms_handle_t)); - desc->ifspec = ifspec; - desc->discrim = discrim; - desc->next = mlsvc_desc_list; - mlsvc_desc_list = desc; - - if (key) - (void) strlcpy(desc->key, key, MLSVC_HANDLE_KEY_MAX); - else - desc->key[0] = '\0'; - - return (&mlsvc_handle); -} - - -/* - * mlsvc_put_handle - * - * Remove a handle from the global handle descriptor list and free the - * memory it was using. If the list contained the descriptor, a value - * of 0 is returned. Otherwise -1 is returned. - */ -int -mlsvc_put_handle(ms_handle_t *handle) -{ - ms_handle_desc_t *desc; - ms_handle_desc_t **ppdesc = &mlsvc_desc_list; - - assert(handle); - - while (*ppdesc) { - desc = *ppdesc; - - if (bcmp(&desc->handle, handle, sizeof (ms_handle_t)) == 0) { - *ppdesc = desc->next; - free(desc); - return (0); - } - - ppdesc = &(*ppdesc)->next; - } - - return (-1); -} - - -/* - * mlsvc_validate_handle - * - * Lookup a handle in the global handle descriptor list. If the handle - * is in the list, a pointer to the descriptor is returned. Otherwise - * a null pointer is returned. - */ -int -mlsvc_validate_handle(ms_handle_t *handle, char *key) -{ - ms_handle_desc_t *desc; - - assert(handle); - assert(key); - - if ((desc = mlsvc_lookup_handle(handle)) == 0) - return (NULL); - - if (strcmp(desc->key, key)) - return (NULL); - - return (1); -} - - -/* - * mlsvc_lookup_handle - * - * Lookup a handle in the global handle descriptor list. If the handle - * is in the list, a pointer to the descriptor is returned. Otherwise - * a null pointer is returned. - */ -ms_handle_desc_t * -mlsvc_lookup_handle(ms_handle_t *handle) -{ - ms_handle_desc_t *desc = mlsvc_desc_list; - - assert(handle); - - while (desc) { - if (bcmp(&desc->handle, handle, sizeof (ms_handle_t)) == 0) - return (desc); - - desc = desc->next; - } - - return (NULL); -} diff --git a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_init.c b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_init.c index fc17554949..cd8ec7da36 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_init.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_init.c @@ -19,19 +19,15 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" -#include <stdio.h> #include <unistd.h> - -#include <smbsrv/libsmb.h> +#include <pthread.h> #include <smbsrv/libmlsvc.h> -#include <smbsrv/mlsvc_util.h> -#include <smbsrv/lsalib.h> void dssetup_initialize(void); void srvsvc_initialize(void); @@ -42,6 +38,12 @@ void netr_initialize(void); void samr_initialize(void); void svcctl_initialize(void); void winreg_initialize(void); +int srvsvc_gettime(unsigned long *); + +static void *mlsvc_keepalive(void *); + +static pthread_t mlsvc_keepalive_thr; +#define MLSVC_KEEPALIVE_INTERVAL (10 * 60) /* 10 minutes */ /* * All mlrpc initialization is invoked from here. @@ -50,6 +52,9 @@ void winreg_initialize(void); int mlsvc_init(void) { + pthread_attr_t tattr; + int rc; + srvsvc_initialize(); wkssvc_initialize(); lsarpc_initialize(); @@ -60,6 +65,35 @@ mlsvc_init(void) winreg_initialize(); logr_initialize(); - (void) sam_init(); - return (0); + (void) lsa_query_primary_domain_info(); + + (void) pthread_attr_init(&tattr); + (void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED); + rc = pthread_create(&mlsvc_keepalive_thr, &tattr, + mlsvc_keepalive, 0); + (void) pthread_attr_destroy(&tattr); + return (rc); +} + +/*ARGSUSED*/ +static void * +mlsvc_keepalive(void *arg) +{ + unsigned long t; + nt_domain_t *domain; + + for (;;) { + (void) sleep(MLSVC_KEEPALIVE_INTERVAL); + + if (smb_config_get_secmode() == SMB_SECMODE_DOMAIN) { + domain = nt_domain_lookupbytype(NT_DOMAIN_PRIMARY); + if (domain == NULL) + (void) lsa_query_primary_domain_info(); + } + + (void) srvsvc_gettime(&t); + } + + /*NOTREACHED*/ + return (NULL); } diff --git a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_logr.c b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_logr.c index 4a6c80613d..3070561173 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_logr.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_logr.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -195,7 +195,6 @@ typedef struct { } read_data_t; static char logr_sysname[SYS_NMLN]; -static char hostname[MAXHOSTNAMELEN]; static mts_wchar_t wcs_hostname[MAXHOSTNAMELEN]; static int hostname_len = 0; static mts_wchar_t wcs_srcname[MAX_SRCNAME_LEN]; @@ -231,26 +230,25 @@ logr_initialize(void) /* * logr_s_EventLogClose * - * This is a request to close the LOGR interface specified by the - * handle. Free the handle and its associated resources and zero out - * the result handle for the client. + * This is a request to close the LOGR interface specified by handle. + * Free the handle and associated resources, and zero out the result + * handle for the client. */ -/*ARGSUSED*/ static int logr_s_EventLogClose(void *arg, struct mlrpc_xaction *mxa) { struct logr_EventLogClose *param = arg; - ms_handle_desc_t *desc; - read_data_t *data; + ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; + ndr_handle_t *hd; - if ((desc = mlsvc_lookup_handle((ms_handle_t *)¶m->handle)) == 0) { + if ((hd = ndr_hdlookup(mxa, id)) == NULL) { + bzero(¶m->result_handle, sizeof (logr_handle_t)); param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE); return (MLRPC_DRC_OK); } - data = (read_data_t *)(uintptr_t)(desc->discrim); - free(data); - (void) mlsvc_put_handle((ms_handle_t *)¶m->handle); + free(hd->nh_data); + ndr_hdfree(mxa, id); bzero(¶m->result_handle, sizeof (logr_handle_t)); param->status = NT_STATUS_SUCCESS; @@ -260,40 +258,16 @@ logr_s_EventLogClose(void *arg, struct mlrpc_xaction *mxa) /* * logr_s_EventLogOpen * - * This is a request to open the event log. - * - * Return a handle for use with subsequent event log requests. + * Open the event log. Not supported yet. */ /*ARGSUSED*/ static int logr_s_EventLogOpen(void *arg, struct mlrpc_xaction *mxa) { struct logr_EventLogOpen *param = arg; - ms_handle_t *handle; - int log_enable = 0; - int len; - int rc; - smb_config_rdlock(); - log_enable = smb_config_getyorn(SMB_CI_LOGR_ENABLE); - smb_config_unlock(); - - rc = smb_gethostname(hostname, MAXHOSTNAMELEN, 1); - - if (log_enable == 0 || rc != 0) { - bzero(¶m->handle, sizeof (logr_handle_t)); - param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED); - return (MLRPC_DRC_OK); - } - - handle = mlsvc_get_handle(MLSVC_IFSPEC_LOGR, LOGR_KEY, 0); - bcopy(handle, ¶m->handle, sizeof (logr_handle_t)); - - len = strlen(hostname) + 1; - (void) mts_mbstowcs(wcs_hostname, hostname, len); - hostname_len = len * sizeof (mts_wchar_t); - - param->status = NT_STATUS_SUCCESS; + bzero(¶m->handle, sizeof (logr_handle_t)); + param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED); return (MLRPC_DRC_OK); } @@ -316,15 +290,15 @@ logr_get_snapshot(void) * return number of log entries in the snapshot as result of RPC * call. */ -/*ARGSUSED*/ static int logr_s_EventLogQueryCount(void *arg, struct mlrpc_xaction *mxa) { struct logr_EventLogQueryCount *param = arg; - ms_handle_desc_t *desc; + ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; + ndr_handle_t *hd; read_data_t *data; - if ((desc = mlsvc_lookup_handle((ms_handle_t *)¶m->handle)) == 0) { + if ((hd = ndr_hdlookup(mxa, id)) == NULL) { param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE); return (MLRPC_DRC_OK); } @@ -334,7 +308,7 @@ logr_s_EventLogQueryCount(void *arg, struct mlrpc_xaction *mxa) return (MLRPC_DRC_OK); } - desc->discrim = (DWORD)(uintptr_t)data; + hd->nh_data = data; param->rec_num = data->tot_recnum; param->status = NT_STATUS_SUCCESS; return (MLRPC_DRC_OK); @@ -345,21 +319,20 @@ logr_s_EventLogQueryCount(void *arg, struct mlrpc_xaction *mxa) * * Return oldest record number in the snapshot as result of RPC call. */ -/*ARGSUSED*/ static int logr_s_EventLogGetOldestRec(void *arg, struct mlrpc_xaction *mxa) { struct logr_EventLogGetOldestRec *param = arg; - ms_handle_desc_t *desc; + ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; + ndr_handle_t *hd; read_data_t *data; - desc = mlsvc_lookup_handle((ms_handle_t *)¶m->handle); - if (desc == NULL) { + if ((hd = ndr_hdlookup(mxa, id)) == NULL) { param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE); return (MLRPC_DRC_OK); } - data = (read_data_t *)(uintptr_t)desc->discrim; + data = (read_data_t *)hd->nh_data; param->oldest_rec = data->log.ix - data->tot_recnum; param->status = NT_STATUS_SUCCESS; return (MLRPC_DRC_OK); @@ -452,12 +425,12 @@ set_logrec(log_entry_t *le, DWORD recno, logr_record_t *rec) * Reads a whole number of entries from system log. The function can * read log entries in chronological or reverse chronological order. */ -/*ARGSUSED*/ static int logr_s_EventLogRead(void *arg, struct mlrpc_xaction *mxa) { struct logr_EventLogRead *param = arg; - ms_handle_desc_t *desc; + ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; + ndr_handle_t *hd; read_data_t *rdata; log_entry_t *le; DWORD ent_no, ent_num, ent_remain; @@ -465,20 +438,19 @@ logr_s_EventLogRead(void *arg, struct mlrpc_xaction *mxa) BYTE *buf; int dir, ent_per_req; - desc = mlsvc_lookup_handle((ms_handle_t *)¶m->handle); - if (desc == NULL) { + if ((hd = ndr_hdlookup(mxa, id)) == NULL) { param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE); return (MLRPC_DRC_OK); } - rdata = (read_data_t *)(uintptr_t)(desc->discrim); - if (rdata == 0) { + rdata = (read_data_t *)hd->nh_data; + if (rdata == NULL) { if ((rdata = logr_get_snapshot()) == NULL) { param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY); return (MLRPC_DRC_OK); } - desc->discrim = (DWORD)(uintptr_t)rdata; + hd->nh_data = rdata; } dir = (param->read_flags & EVENTLOG_FORWARDS_READ) ? FWD : REW; diff --git a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_lsa.c b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_lsa.c index 4d770edbc1..0bc4206f3d 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_lsa.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_lsa.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -54,6 +54,9 @@ struct local_group_table { char *name; }; +static int lsarpc_key_domain; +static int lsarpc_key_account; + static int lsarpc_call_stub(struct mlrpc_xaction *mxa); static int lsarpc_s_CloseHandle(void *arg, struct mlrpc_xaction *); @@ -78,14 +81,6 @@ static int lsarpc_s_PrimaryDomainInfo(struct mslsa_PrimaryDomainInfo *, struct mlrpc_xaction *); static int lsarpc_s_AccountDomainInfo(struct mslsa_AccountDomainInfo *, struct mlrpc_xaction *); -static int lsarpc_s_LookupNtSid(struct mlrpc_xaction *, nt_sid_t *, - smb_userinfo_t *, struct mslsa_name_entry *, int); -static int lsarpc_s_LookupLocalSid(struct mlrpc_xaction *, nt_sid_t *, - smb_userinfo_t *, struct mslsa_name_entry *); -static int lsarpc_s_LookupBuiltinSid(struct mlrpc_xaction *, nt_sid_t *, - smb_userinfo_t *, struct mslsa_name_entry *); -static int lsarpc_s_UnknownSid(struct mlrpc_xaction *, nt_sid_t *, - smb_userinfo_t *, struct mslsa_name_entry *); static int lsarpc_s_UpdateDomainTable(struct mlrpc_xaction *, smb_userinfo_t *, struct mslsa_domain_table *, DWORD *); @@ -177,22 +172,21 @@ lsarpc_call_stub(struct mlrpc_xaction *mxa) * lsarpc_s_OpenDomainHandle opnum=0x06 * * This is a request to open the LSA (OpenPolicy and OpenPolicy2). - * The client is looking for an LSA domain handle. Handles appear to - * be a 20 byte opaque object with the top 4 bytes all zero. As it is - * opaque to the client, we can put anything we like in it. Real handles - * do appear to contain a sequence number which is incremented when a - * new handle is issued. However, we don't really care about that - * (yet). Always return MLRPC_DRC_OK. + * The client is looking for an LSA domain handle. */ -/*ARGSUSED*/ static int lsarpc_s_OpenDomainHandle(void *arg, struct mlrpc_xaction *mxa) { struct mslsa_OpenPolicy2 *param = arg; + ndr_hdid_t *id; - bzero(¶m->domain_handle, sizeof (mslsa_handle_t)); - (void) strcpy((char *)¶m->domain_handle.hand2, "DomainHandle"); - param->status = 0; + if ((id = ndr_hdalloc(mxa, &lsarpc_key_domain)) != NULL) { + bcopy(id, ¶m->domain_handle, sizeof (mslsa_handle_t)); + param->status = NT_STATUS_SUCCESS; + } else { + bzero(¶m->domain_handle, sizeof (mslsa_handle_t)); + param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY); + } return (MLRPC_DRC_OK); } @@ -205,15 +199,16 @@ lsarpc_s_OpenDomainHandle(void *arg, struct mlrpc_xaction *mxa) * MLRPC_DRC_OK. Setting the handle to zero appears to be standard * behaviour and someone may rely on it, i.e. we do on the client side. */ -/*ARGSUSED*/ static int lsarpc_s_CloseHandle(void *arg, struct mlrpc_xaction *mxa) { struct mslsa_CloseHandle *param = arg; + ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; - bzero(¶m->result_handle, sizeof (param->result_handle)); - param->status = 0; + ndr_hdfree(mxa, id); + bzero(¶m->result_handle, sizeof (param->result_handle)); + param->status = NT_STATUS_SUCCESS; return (MLRPC_DRC_OK); } @@ -307,23 +302,28 @@ lsarpc_s_EnumTrustedDomain(void *arg, struct mlrpc_xaction *mxa) /* * lsarpc_s_OpenAccount * - * This is a request to open an account handle. This function hasn't - * been tested. It is just a template in case some server somewhere - * makes this call. See lsarpc_s_OpenDomainHandle for more information. + * This is a request to open an account handle. */ -/*ARGSUSED*/ static int lsarpc_s_OpenAccount(void *arg, struct mlrpc_xaction *mxa) { struct mslsa_OpenAccount *param = arg; + ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; + ndr_handle_t *hd; + + hd = ndr_hdlookup(mxa, id); + if ((hd == NULL) || (hd->nh_data != &lsarpc_key_domain)) { + bzero(¶m, sizeof (struct mslsa_OpenAccount)); + param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE); + return (MLRPC_DRC_OK); + } - if (param->handle.hand1 != 0 || - strcmp("DomainHandle", (char *)¶m->handle.hand2)) { - param->status = NT_SC_ERROR(ERROR_NO_SUCH_DOMAIN); + if ((id = ndr_hdalloc(mxa, &lsarpc_key_account)) != NULL) { + bcopy(id, ¶m->account_handle, sizeof (mslsa_handle_t)); + param->status = NT_STATUS_SUCCESS; } else { - (void) strcpy((char *)¶m->account_handle.hand2, - "AccountHandle"); - param->status = 0; + bzero(¶m->account_handle, sizeof (mslsa_handle_t)); + param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY); } return (MLRPC_DRC_OK); @@ -584,7 +584,7 @@ lsarpc_s_PrimaryDomainInfo(struct mslsa_PrimaryDomainInfo *pd_info, status = NT_STATUS_SUCCESS; - security_mode = smb_get_security_mode(); + security_mode = smb_config_get_secmode(); if (security_mode != SMB_SECMODE_DOMAIN) { rc = smb_gethostname(domain_name, MLSVC_DOMAIN_NAME_MAX, 1); @@ -686,8 +686,8 @@ lsarpc_s_LookupNames(void *arg, struct mlrpc_xaction *mxa) smb_userinfo_t *user_info = 0; struct mslsa_domain_table *domain_table; struct mslsa_domain_entry *domain_entry; - char *name = ""; DWORD status = NT_STATUS_SUCCESS; + char *account; int rc = 0; if (param->name_table->n_entry != 1) @@ -704,20 +704,10 @@ lsarpc_s_LookupNames(void *arg, struct mlrpc_xaction *mxa) goto name_lookup_failed; } - name = (char *)param->name_table->names->str; - - rc = lsa_lookup_local(name, user_info); - if (rc < 0) { - status = NT_STATUS_NO_SUCH_USER; + account = (char *)param->name_table->names->str; + status = lsa_lookup_name(NULL, account, SidTypeUnknown, user_info); + if (status != NT_STATUS_SUCCESS) goto name_lookup_failed; - } - - if (rc > 0) { - if (lsa_lookup_name(0, 0, name, user_info) != 0) { - status = NT_STATUS_NO_SUCH_USER; - goto name_lookup_failed; - } - } /* * Set up the rid table. @@ -780,6 +770,7 @@ lsarpc_s_LookupSids(void *arg, struct mlrpc_xaction *mxa) struct mslsa_domain_table *domain_table; struct mslsa_domain_entry *domain_entry; struct mslsa_name_entry *names; + struct mslsa_name_entry *name; smb_userinfo_t *user_info; nt_sid_t *sid; DWORD n_entry; @@ -805,48 +796,28 @@ lsarpc_s_LookupSids(void *arg, struct mlrpc_xaction *mxa) domain_table->n_entry = 0; domain_table->max_n_entry = MLSVC_DOMAIN_MAX; - for (i = 0; i < n_entry; ++i) { + name = names; + for (i = 0; i < n_entry; ++i, name++) { bzero(&names[i], sizeof (struct mslsa_name_entry)); sid = (nt_sid_t *)param->lup_sid_table.entries[i].psid; - if (nt_sid_is_local(sid)) { - result = lsarpc_s_LookupLocalSid(mxa, sid, user_info, - &names[i]); - } else { - result = lsarpc_s_LookupBuiltinSid(mxa, sid, user_info, - &names[i]); - - if (result != 0) - result = lsarpc_s_LookupNtSid(mxa, sid, - user_info, &names[i], 1); + result = lsa_lookup_sid(sid, user_info); + if (result != NT_STATUS_SUCCESS) + goto lookup_sid_failed; - if (result != 0) { - result = lsarpc_s_UnknownSid(mxa, sid, - user_info, &names[i]); - } - } - - if (result == -1) { - mlsvc_free_user_info(user_info); - param->domain_table = 0; - param->name_table.n_entry = 0; - param->name_table.entries = 0; - param->mapped_count = 0; - param->status = NT_SC_ERROR(NT_STATUS_INVALID_SID); - return (MLRPC_DRC_OK); + if (!mlsvc_string_save((ms_string_t *)&name->name, + user_info->name, mxa)) { + result = NT_STATUS_NO_MEMORY; + goto lookup_sid_failed; } + name->sid_name_use = user_info->sid_name_use; result = lsarpc_s_UpdateDomainTable(mxa, user_info, - domain_table, &names[i].domain_ix); + domain_table, &name->domain_ix); if (result == -1) { - mlsvc_free_user_info(user_info); - param->domain_table = 0; - param->name_table.n_entry = 0; - param->name_table.entries = 0; - param->mapped_count = 0; - param->status = NT_SC_ERROR(NT_STATUS_INVALID_SID); - return (MLRPC_DRC_OK); + result = NT_STATUS_INTERNAL_ERROR; + goto lookup_sid_failed; } mlsvc_release_user_info(user_info); @@ -860,295 +831,16 @@ lsarpc_s_LookupSids(void *arg, struct mlrpc_xaction *mxa) mlsvc_free_user_info(user_info); return (MLRPC_DRC_OK); -} - -/* - * lsarpc_s_LookupLocalSid - * - * This function handles local domain SID lookup. If the SID matches the - * local domain SID, we lookup the local files to map the RID to a name. - * We attempt to handle both users and groups. When the SID was supplied - * to the client, the ID type should have been encoded in the RID. We - * decode the RID and lookup it up in either the passwd file or the - * group file as appropriate. - * - * On success, 0 is returned. Otherwise -1 is returned. - */ -static int -lsarpc_s_LookupLocalSid(struct mlrpc_xaction *mxa, nt_sid_t *sid, - smb_userinfo_t *user_info, struct mslsa_name_entry *name) -{ - char buffer[MLSVC_DOMAIN_NAME_MAX]; - char namebuf[MLSVC_DOMAIN_NAME_MAX]; - nt_sid_t *lds; - nt_sid_t *tmp_sid; - nt_group_t *grp; - struct passwd *pw; - struct group *gr; - DWORD rid; - int unix_id; - - if (smb_gethostname(buffer, MLSVC_DOMAIN_NAME_MAX, 1) != 0) - return (-1); - - /* - * Only free tmp_sid in error paths. If it is assigned to the - * user_info, it will be freed later when that structure is - * released. - */ - if ((tmp_sid = nt_sid_dup(sid)) == NULL) - return (-1); - - rid = 0; - lds = nt_domain_local_sid(); - user_info->sid_name_use = SidTypeInvalid; - - if (nt_sid_is_equal(lds, tmp_sid)) { - user_info->sid_name_use = SidTypeDomain; - user_info->name = strdup(buffer); - } else { - (void) nt_sid_split(tmp_sid, &rid); - - switch (SAM_RID_TYPE(rid)) { - case SAM_RT_NT_UID: - break; - - case SAM_RT_NT_GID: - user_info->sid_name_use = SidTypeAlias; - grp = nt_groups_lookup_rid(rid); - if (grp) - user_info->name = strdup(grp->name); - else { - (void) snprintf(namebuf, sizeof (namebuf), - "%d (no name)", rid); - user_info->name = strdup(namebuf); - } - break; - - case SAM_RT_UNIX_UID: - /* - * It is always possible that the rid will not - * correspond to an entry in the local passwd or group - * file. In this case we can return the RID with a - * message to indicate the problem, which seems better - * than returning an invalid SID error. - */ - unix_id = SAM_DECODE_RID(rid); - (void) snprintf(namebuf, sizeof (namebuf), - "%d (no name)", unix_id); - user_info->sid_name_use = SidTypeUser; - pw = getpwuid(unix_id); - user_info->name = (pw) ? - strdup(pw->pw_name) : strdup(namebuf); - break; - - case SAM_RT_UNIX_GID: - unix_id = SAM_DECODE_RID(rid); - (void) snprintf(namebuf, sizeof (namebuf), - "%d (no name)", unix_id); - user_info->sid_name_use = SidTypeAlias; - gr = getgrgid(unix_id); - user_info->name = (gr) ? - strdup(gr->gr_name) : strdup(namebuf); - break; - } - } - - if (user_info->sid_name_use == SidTypeInvalid) { - free(tmp_sid); - return (-1); - } - /* - * Set up the rest of user_info. - * Don't free tmp_sid after this. - */ - user_info->rid = rid; - user_info->domain_name = strdup(buffer); - user_info->domain_sid = tmp_sid; - - bzero(name, sizeof (struct mslsa_name_entry)); - name->sid_name_use = user_info->sid_name_use; - - if (!mlsvc_string_save( - (ms_string_t *)&name->name, user_info->name, mxa)) { - return (-1); - } +lookup_sid_failed: + param->domain_table = 0; + param->name_table.n_entry = 0; + param->name_table.entries = 0; + param->mapped_count = 0; + param->status = NT_SC_ERROR(result); - return (0); -} - -/* - * lsarpc_s_LookupNtSid - * - * This function handles NT domain SID lookup on the domain controller. - * Most of the work is performed by lsa_lookup_sid. We just have to - * update the name data for the response. It is assumed that any SID - * passed to this function has already been checked and correctly - * identified as an NT domain SID. It shouldn't break anything if you - * get it wrong, the domain controller will just reject the SID. - * - * On success, 0 is returned. Otherwise -1 is returned. - */ -static int -lsarpc_s_LookupNtSid(struct mlrpc_xaction *mxa, nt_sid_t *sid, - smb_userinfo_t *user_info, struct mslsa_name_entry *name, int version) -{ - char *username; - DWORD status; - - if (smb_getdomaininfo(0) == 0) { - status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO; - return (-1); - } - - if (version == 2) - status = lsa_lookup_sid2(sid, user_info); - else - status = lsa_lookup_sid(sid, user_info); - - if (status != 0) - return (-1); - - switch (user_info->sid_name_use) { - case SidTypeDomain: - if ((username = user_info->domain_name) == 0) - user_info->sid_name_use = SidTypeUnknown; - break; - - case SidTypeUser: - case SidTypeGroup: - case SidTypeAlias: - case SidTypeDeletedAccount: - case SidTypeWellKnownGroup: - if ((username = user_info->name) == 0) - user_info->sid_name_use = SidTypeUnknown; - break; - - default: - return (-1); - } - - if (username == 0) - username = "unknown"; - bzero(name, sizeof (struct mslsa_name_entry)); - name->sid_name_use = user_info->sid_name_use; - - if (!mlsvc_string_save((ms_string_t *)&name->name, username, mxa)) - return (-1); - - return (0); -} - -/* - * lsarpc_s_LookupBuiltinSid - * - * This function handles predefined local groups and aliases in the NT - * AUTHORITY or BUILTIN domains, and some other miscellaneous bits. I - * don't think NT cares about the domain field of well-known groups or - * aliases but it seems sensible to set it up anyway. If we get a match, - * set up the name in the response heap. - * - * On success, 0 is returned. Otherwise non-zero is returned. A non-zero - * return value should not be automatically interpreted as an error. The - * caller should attempt to resolve the SID through alternative means. - */ -static int -lsarpc_s_LookupBuiltinSid(struct mlrpc_xaction *mxa, nt_sid_t *sid, - smb_userinfo_t *user_info, struct mslsa_name_entry *name) -{ - char *np; - WORD sid_name_use; - - if ((np = nt_builtin_lookup_sid(sid, &sid_name_use)) == NULL) - return (1); - - user_info->sid_name_use = sid_name_use; - user_info->name = strdup(np); - user_info->domain_sid = nt_sid_dup(sid); - - if (user_info->name == NULL || user_info->domain_sid == NULL) { - mlsvc_release_user_info(user_info); - return (-1); - } - - if (sid_name_use != SidTypeDomain && sid->SubAuthCount != 0) - user_info->rid = sid->SubAuthority[sid->SubAuthCount - 1]; - else - user_info->rid = 0; - - if ((np = nt_builtin_lookup_domain(user_info->name)) != NULL) - user_info->domain_name = strdup(np); - else - user_info->domain_name = strdup("UNKNOWN"); - - if (user_info->domain_name == NULL) { - mlsvc_release_user_info(user_info); - return (-1); - } - - if (sid_name_use == SidTypeAlias && - user_info->domain_sid->SubAuthCount != 0) { - --user_info->domain_sid->SubAuthCount; - } - - bzero(name, sizeof (struct mslsa_name_entry)); - name->sid_name_use = sid_name_use; - - if (sid_name_use == SidTypeUnknown) { - mlsvc_release_user_info(user_info); - return (1); - } - - if (!mlsvc_string_save( - (ms_string_t *)&name->name, user_info->name, mxa)) { - mlsvc_release_user_info(user_info); - return (-1); - } - - return (0); -} - -/* - * lsarpc_s_UnknownSid - * - * This function handles unknown SIDs. By the time this is called we - * know that this is not a local SID and that the PDC has no idea to - * whom this sid refers. It may be a remnant from a time when the - * server was in another domain. All we can do is turn into the SID - * into a string and return it in place of a user name. - * - * On success, 0 is returned. Otherwise -1 is returned. - */ -static int -lsarpc_s_UnknownSid(struct mlrpc_xaction *mxa, nt_sid_t *sid, - smb_userinfo_t *user_info, struct mslsa_name_entry *name) -{ - char domain_name[MLSVC_DOMAIN_NAME_MAX]; - char *sidbuf; - - if ((sidbuf = nt_sid_format(sid)) == NULL) - return (-1); - - if (smb_gethostname(domain_name, MLSVC_DOMAIN_NAME_MAX, 1) != 0) - return (-1); - - (void) utf8_strupr(domain_name); - mlsvc_release_user_info(user_info); - user_info->sid_name_use = SidTypeUnknown; - user_info->name = sidbuf; - user_info->domain_name = strdup(domain_name); - user_info->domain_sid = nt_sid_dup(nt_domain_local_sid()); - - bzero(name, sizeof (struct mslsa_name_entry)); - name->sid_name_use = user_info->sid_name_use; - - if (!mlsvc_string_save( - (ms_string_t *)&name->name, user_info->name, mxa)) { - return (-1); - } - - return (0); + mlsvc_free_user_info(user_info); + return (MLRPC_DRC_OK); } /* @@ -1223,6 +915,7 @@ lsarpc_s_LookupSids2(void *arg, struct mlrpc_xaction *mxa) { struct lsar_lookup_sids2 *param = arg; struct lsar_name_entry2 *names; + struct lsar_name_entry2 *name; struct mslsa_domain_table *domain_table; struct mslsa_domain_entry *domain_entry; smb_userinfo_t *user_info; @@ -1250,51 +943,28 @@ lsarpc_s_LookupSids2(void *arg, struct mlrpc_xaction *mxa) domain_table->n_entry = 0; domain_table->max_n_entry = MLSVC_DOMAIN_MAX; - for (i = 0; i < n_entry; ++i) { - bzero(&names[i], sizeof (struct lsar_name_entry2)); + name = names; + for (i = 0; i < n_entry; ++i, name++) { + bzero(name, sizeof (struct lsar_name_entry2)); sid = (nt_sid_t *)param->lup_sid_table.entries[i].psid; - if (nt_sid_is_local(sid)) { - result = lsarpc_s_LookupLocalSid(mxa, sid, user_info, - (struct mslsa_name_entry *)&names[i]); - } else { - result = lsarpc_s_LookupBuiltinSid(mxa, sid, user_info, - (struct mslsa_name_entry *)&names[i]); - - if (result != 0) - result = lsarpc_s_LookupNtSid(mxa, sid, - user_info, - (struct mslsa_name_entry *)&names[i], 2); - - if (result != 0) { - result = lsarpc_s_UnknownSid(mxa, sid, - user_info, - (struct mslsa_name_entry *)&names[i]); - } - } + result = lsa_lookup_sid(sid, user_info); + if (result != NT_STATUS_SUCCESS) + goto lookup_sid_failed; - if (result == -1) { - mlsvc_free_user_info(user_info); - param->domain_table = 0; - param->name_table.n_entry = 0; - param->name_table.entries = 0; - param->mapped_count = 0; - param->status = NT_SC_ERROR(NT_STATUS_INVALID_SID); - return (MLRPC_DRC_OK); + if (!mlsvc_string_save((ms_string_t *)&name->name, + user_info->name, mxa)) { + result = NT_STATUS_NO_MEMORY; + goto lookup_sid_failed; } + name->sid_name_use = user_info->sid_name_use; result = lsarpc_s_UpdateDomainTable(mxa, user_info, - domain_table, &names[i].domain_ix); + domain_table, &name->domain_ix); if (result == -1) { - mlsvc_free_user_info(user_info); - param->domain_table = 0; - param->name_table.n_entry = 0; - param->name_table.entries = 0; - param->mapped_count = 0; - param->status = NT_SC_ERROR(NT_STATUS_INVALID_SID); - - return (MLRPC_DRC_OK); + result = NT_STATUS_INTERNAL_ERROR; + goto lookup_sid_failed; } mlsvc_release_user_info(user_info); @@ -1308,6 +978,16 @@ lsarpc_s_LookupSids2(void *arg, struct mlrpc_xaction *mxa) mlsvc_free_user_info(user_info); return (MLRPC_DRC_OK); + +lookup_sid_failed: + param->domain_table = 0; + param->name_table.n_entry = 0; + param->name_table.entries = 0; + param->mapped_count = 0; + param->status = NT_SC_ERROR(result); + + mlsvc_free_user_info(user_info); + return (MLRPC_DRC_OK); } /* @@ -1324,7 +1004,7 @@ lsarpc_s_LookupNames2(void *arg, struct mlrpc_xaction *mxa) smb_userinfo_t *user_info = 0; struct mslsa_domain_table *domain_table; struct mslsa_domain_entry *domain_entry; - char *name = ""; + char *account; DWORD status = NT_STATUS_SUCCESS; int rc = 0; @@ -1342,20 +1022,10 @@ lsarpc_s_LookupNames2(void *arg, struct mlrpc_xaction *mxa) goto name_lookup2_failed; } - name = (char *)param->name_table->names->str; - - rc = lsa_lookup_local(name, user_info); - if (rc < 0) { - status = NT_STATUS_NONE_MAPPED; + account = (char *)param->name_table->names->str; + status = lsa_lookup_name(NULL, account, SidTypeUnknown, user_info); + if (status != NT_STATUS_SUCCESS) goto name_lookup2_failed; - } - - if (rc > 0) { - if (lsa_lookup_name2(0, 0, name, user_info) != 0) { - status = NT_STATUS_NONE_MAPPED; - goto name_lookup2_failed; - } - } /* * Set up the rid table. diff --git a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_sam.c b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_sam.c index 6d22e62127..3be04d2a50 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_sam.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_sam.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -47,28 +47,31 @@ #include <smbsrv/samlib.h> /* - * The keys associated with the various handles dispensed - * by the SAMR server. These keys can be used to validate - * client activity. These values are never passed over - * the network so security shouldn't be an issue. + * The keys associated with the various handles dispensed by the SAMR + * server. These keys can be used to validate client activity. + * These values are never passed over the wire so security shouldn't + * be an issue. */ -#define SAMR_CONNECT_KEY "SamrConnect" -#define SAMR_DOMAIN_KEY "SamrDomain" -#define SAMR_USER_KEY "SamrUser" -#define SAMR_GROUP_KEY "SamrGroup" -#define SAMR_ALIAS_KEY "SamrAlias" - -/* - * Domain discriminator values. Set the top bit to try - * to distinguish these values from user and group ids. - */ -#define SAMR_DATABASE_DOMAIN 0x80000001 -#define SAMR_LOCAL_DOMAIN 0x80000002 -#define SAMR_BUILTIN_DOMAIN 0x80000003 -#define SAMR_PRIMARY_DOMAIN 0x80000004 - +typedef enum { + SAMR_KEY_NULL = 0, + SAMR_KEY_CONNECT, + SAMR_KEY_DOMAIN, + SAMR_KEY_USER, + SAMR_KEY_GROUP, + SAMR_KEY_ALIAS +} samr_key_t; + +typedef struct samr_keydata { + samr_key_t kd_key; + nt_domain_type_t kd_type; + DWORD kd_rid; +} samr_keydata_t; + +static ndr_hdid_t *samr_hdalloc(ndr_xa_t *, samr_key_t, nt_domain_type_t, + DWORD); +static void samr_hdfree(ndr_xa_t *, ndr_hdid_t *); +static ndr_handle_t *samr_hdlookup(ndr_xa_t *, ndr_hdid_t *, samr_key_t); static int samr_call_stub(struct mlrpc_xaction *mxa); - static DWORD samr_s_enum_local_domains(struct samr_EnumLocalDomain *, struct mlrpc_xaction *); @@ -115,6 +118,60 @@ samr_call_stub(struct mlrpc_xaction *mxa) } /* + * Handle allocation wrapper to setup the local context. + */ +static ndr_hdid_t * +samr_hdalloc(ndr_xa_t *mxa, samr_key_t key, nt_domain_type_t domain_type, + DWORD rid) +{ + samr_keydata_t *data; + + if ((data = malloc(sizeof (samr_keydata_t))) == NULL) + return (NULL); + + data->kd_key = key; + data->kd_type = domain_type; + data->kd_rid = rid; + + return (ndr_hdalloc(mxa, data)); +} + +/* + * Handle deallocation wrapper to free the local context. + */ +static void +samr_hdfree(ndr_xa_t *mxa, ndr_hdid_t *id) +{ + ndr_handle_t *hd; + + if ((hd = ndr_hdlookup(mxa, id)) != NULL) { + free(hd->nh_data); + ndr_hdfree(mxa, id); + } +} + +/* + * Handle lookup wrapper to validate the local context. + */ +static ndr_handle_t * +samr_hdlookup(ndr_xa_t *mxa, ndr_hdid_t *id, samr_key_t key) +{ + ndr_handle_t *hd; + samr_keydata_t *data; + + if ((hd = ndr_hdlookup(mxa, id)) == NULL) + return (NULL); + + if ((data = (samr_keydata_t *)hd->nh_data) == NULL) + return (NULL); + + if (data->kd_key != key) + return (NULL); + + return (hd); +} + +/* * samr_s_ConnectAnon * * This is a request to connect to the local SAM database. We don't @@ -124,44 +181,38 @@ samr_call_stub(struct mlrpc_xaction *mxa) * * Return a handle for use with subsequent SAM requests. */ -/*ARGSUSED*/ static int samr_s_ConnectAnon(void *arg, struct mlrpc_xaction *mxa) { struct samr_ConnectAnon *param = arg; - ms_handle_t *handle; + ndr_hdid_t *id; - handle = mlsvc_get_handle(MLSVC_IFSPEC_SAMR, SAMR_CONNECT_KEY, - SAMR_DATABASE_DOMAIN); - bcopy(handle, ¶m->handle, sizeof (samr_handle_t)); + id = samr_hdalloc(mxa, SAMR_KEY_CONNECT, NT_DOMAIN_NULL, 0); + if (id) { + bcopy(id, ¶m->handle, sizeof (samr_handle_t)); + param->status = 0; + } else { + bzero(¶m->handle, sizeof (samr_handle_t)); + param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY); + } - param->status = 0; return (MLRPC_DRC_OK); } /* * samr_s_CloseHandle * - * This is a request to close the SAM interface specified by the handle. + * Close the SAM interface specified by the handle. * Free the handle and zero out the result handle for the client. - * - * We could do some checking here but it probably doesn't matter. */ -/*ARGSUSED*/ static int samr_s_CloseHandle(void *arg, struct mlrpc_xaction *mxa) { struct samr_CloseHandle *param = arg; + ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; -#ifdef SAMR_S_DEBUG - if (mlsvc_lookup_handle((ms_handle_t *)¶m->handle) == 0) { - bzero(¶m->result_handle, sizeof (samr_handle_t)); - param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE); - return (MLRPC_DRC_OK); - } -#endif /* SAMR_S_DEBUG */ + samr_hdfree(mxa, id); - (void) mlsvc_put_handle((ms_handle_t *)¶m->handle); bzero(¶m->result_handle, sizeof (samr_handle_t)); param->status = 0; return (MLRPC_DRC_OK); @@ -179,9 +230,8 @@ static int samr_s_LookupDomain(void *arg, struct mlrpc_xaction *mxa) { struct samr_LookupDomain *param = arg; - char resource_domain[MAXHOSTNAMELEN]; + char resource_domain[SMB_PI_MAX_DOMAIN]; char *domain_name; - char *p; nt_sid_t *sid = NULL; if ((domain_name = (char *)param->domain_name.str) == NULL) { @@ -190,11 +240,7 @@ samr_s_LookupDomain(void *arg, struct mlrpc_xaction *mxa) return (MLRPC_DRC_OK); } - smb_config_rdlock(); - p = smb_config_getstr(SMB_CI_DOMAIN_NAME); - (void) strlcpy(resource_domain, p, MAXHOSTNAMELEN); - smb_config_unlock(); - + (void) smb_getdomainname(resource_domain, SMB_PI_MAX_DOMAIN); if (mlsvc_is_local_domain(domain_name) == 1) { sid = nt_sid_dup(nt_domain_local_sid()); } else if (strcasecmp(resource_domain, domain_name) == 0) { @@ -237,12 +283,10 @@ static int samr_s_EnumLocalDomains(void *arg, struct mlrpc_xaction *mxa) { struct samr_EnumLocalDomain *param = arg; - ms_handle_t *handle; + ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; DWORD status; - handle = (ms_handle_t *)¶m->handle; - - if (mlsvc_validate_handle(handle, SAMR_CONNECT_KEY) == 0) + if (samr_hdlookup(mxa, id, SAMR_KEY_CONNECT) == NULL) status = NT_STATUS_ACCESS_DENIED; else status = samr_s_enum_local_domains(param, mxa); @@ -308,52 +352,42 @@ samr_s_enum_local_domains(struct samr_EnumLocalDomain *param, * samr_s_OpenDomain * * This is a request to open a domain within the local SAM database. - * The caller must supply a valid handle obtained via a successful - * connect. We return a handle to be used to access objects within - * this domain. + * The caller must supply a valid connect handle. + * We return a handle to be used to access objects within this domain. */ -/*ARGSUSED*/ static int samr_s_OpenDomain(void *arg, struct mlrpc_xaction *mxa) { struct samr_OpenDomain *param = arg; - ms_handle_t *handle = 0; + ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; nt_domain_t *domain; - if (!mlsvc_validate_handle( - (ms_handle_t *)¶m->handle, SAMR_CONNECT_KEY)) { + if (samr_hdlookup(mxa, id, SAMR_KEY_CONNECT) == NULL) { bzero(¶m->domain_handle, sizeof (samr_handle_t)); param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED); return (MLRPC_DRC_OK); } - domain = nt_domain_lookup_sid((nt_sid_t *)param->sid); - if (domain == NULL) { + if ((domain = nt_domain_lookup_sid((nt_sid_t *)param->sid)) == NULL) { bzero(¶m->domain_handle, sizeof (samr_handle_t)); param->status = NT_SC_ERROR(NT_STATUS_CANT_ACCESS_DOMAIN_INFO); return (MLRPC_DRC_OK); } - switch (domain->type) { - case NT_DOMAIN_BUILTIN: - handle = mlsvc_get_handle(MLSVC_IFSPEC_SAMR, - SAMR_DOMAIN_KEY, SAMR_BUILTIN_DOMAIN); - - bcopy(handle, ¶m->domain_handle, sizeof (samr_handle_t)); - param->status = 0; - break; - - case NT_DOMAIN_LOCAL: - handle = mlsvc_get_handle(MLSVC_IFSPEC_SAMR, - SAMR_DOMAIN_KEY, SAMR_LOCAL_DOMAIN); + if ((domain->type != NT_DOMAIN_BUILTIN) && + (domain->type != NT_DOMAIN_LOCAL)) { + bzero(¶m->domain_handle, sizeof (samr_handle_t)); + param->status = NT_SC_ERROR(NT_STATUS_CANT_ACCESS_DOMAIN_INFO); + return (MLRPC_DRC_OK); + } - bcopy(handle, ¶m->domain_handle, sizeof (samr_handle_t)); + id = samr_hdalloc(mxa, SAMR_KEY_DOMAIN, domain->type, 0); + if (id) { + bcopy(id, ¶m->domain_handle, sizeof (samr_handle_t)); param->status = 0; - break; - - default: + } else { bzero(¶m->domain_handle, sizeof (samr_handle_t)); - param->status = NT_SC_ERROR(NT_STATUS_CANT_ACCESS_DOMAIN_INFO); + param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY); } return (MLRPC_DRC_OK); @@ -373,13 +407,38 @@ static int samr_s_QueryDomainInfo(void *arg, struct mlrpc_xaction *mxa) { struct samr_QueryDomainInfo *param = arg; - ms_handle_desc_t *desc; - char *hostname; - char *domain_str = ""; + ndr_hdid_t *id = (ndr_hdid_t *)¶m->domain_handle; + ndr_handle_t *hd; + samr_keydata_t *data; + char *domain; + int alias_cnt; int rc; - desc = mlsvc_lookup_handle((ms_handle_t *)¶m->domain_handle); - if (desc == NULL || (strcmp(desc->key, SAMR_DOMAIN_KEY) != 0)) { + if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) { + bzero(param, sizeof (struct samr_QueryDomainInfo)); + param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE); + return (MLRPC_DRC_OK); + } + + data = (samr_keydata_t *)hd->nh_data; + + switch (data->kd_type) { + case NT_DOMAIN_BUILTIN: + domain = "Builtin"; + break; + + case NT_DOMAIN_LOCAL: + domain = MLRPC_HEAP_MALLOC(mxa, MAXHOSTNAMELEN); + rc = smb_gethostname(domain, MAXHOSTNAMELEN, 1); + + if (rc != 0 || domain == NULL) { + bzero(param, sizeof (struct samr_QueryDomainInfo)); + param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY); + return (MLRPC_DRC_OK); + } + break; + + default: bzero(param, sizeof (struct samr_QueryDomainInfo)); param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE); return (MLRPC_DRC_OK); @@ -401,21 +460,13 @@ samr_s_QueryDomainInfo(void *arg, struct mlrpc_xaction *mxa) break; case SAMR_QUERY_DOMAIN_INFO_2: - if (desc->discrim == SAMR_LOCAL_DOMAIN) { - hostname = MLRPC_HEAP_MALLOC(mxa, MAXHOSTNAMELEN); - rc = smb_gethostname(hostname, MAXHOSTNAMELEN, 1); - if (rc != 0 || hostname == NULL) { - bzero(param, - sizeof (struct samr_QueryDomainInfo)); - param->status = - NT_SC_ERROR(NT_STATUS_NO_MEMORY); - return (MLRPC_DRC_OK); - } - - domain_str = hostname; - } else { - if (desc->discrim == SAMR_BUILTIN_DOMAIN) - domain_str = "Builtin"; + rc = (data->kd_type == NT_DOMAIN_BUILTIN) + ? smb_lgrp_numbydomain(SMB_LGRP_BUILTIN, &alias_cnt) + : smb_lgrp_numbydomain(SMB_LGRP_LOCAL, &alias_cnt); + if (rc != SMB_LGRP_SUCCESS) { + bzero(param, sizeof (struct samr_QueryDomainInfo)); + param->status = NT_SC_ERROR(NT_STATUS_INTERNAL_ERROR); + return (MLRPC_DRC_OK); } param->ru.info2.unknown1 = 0x00000000; @@ -425,7 +476,7 @@ samr_s_QueryDomainInfo(void *arg, struct mlrpc_xaction *mxa) "", mxa); (void) mlsvc_string_save( - (ms_string_t *)&(param->ru.info2.domain), domain_str, mxa); + (ms_string_t *)&(param->ru.info2.domain), domain, mxa); (void) mlsvc_string_save((ms_string_t *)&(param->ru.info2.s2), "", mxa); @@ -437,11 +488,7 @@ samr_s_QueryDomainInfo(void *arg, struct mlrpc_xaction *mxa) param->ru.info2.unknown6 = 0x00000001; param->ru.info2.num_users = 0; param->ru.info2.num_groups = 0; - param->ru.info2.num_aliases = - (desc->discrim == SAMR_BUILTIN_DOMAIN) ? - nt_groups_count(NT_GROUP_CNT_BUILTIN) : - nt_groups_count(NT_GROUP_CNT_LOCAL); - + param->ru.info2.num_aliases = alias_cnt; param->status = NT_STATUS_SUCCESS; break; @@ -466,83 +513,85 @@ static int samr_s_LookupNames(void *arg, struct mlrpc_xaction *mxa) { struct samr_LookupNames *param = arg; - ms_handle_desc_t *desc; - struct passwd *pw; - struct group *gr; + ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; + ndr_handle_t *hd; + samr_keydata_t *data; + well_known_account_t *wka; + smb_group_t grp; + smb_passwd_t smbpw; nt_sid_t *sid; - nt_group_t *grp; - WORD rid_type; + uint32_t status = NT_STATUS_SUCCESS; + int rc; - desc = mlsvc_lookup_handle((ms_handle_t *)¶m->handle); - if (desc == 0 || (strcmp(desc->key, SAMR_DOMAIN_KEY) != 0)) { - bzero(param, sizeof (struct samr_LookupNames)); - param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE); - return (MLRPC_DRC_OK); - } + if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) + status = NT_STATUS_INVALID_HANDLE; - if (param->n_entry != 1) { - bzero(param, sizeof (struct samr_LookupNames)); - param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED); - return (MLRPC_DRC_OK); - } + if (param->n_entry != 1) + status = NT_STATUS_ACCESS_DENIED; if (param->name.str == NULL) { - bzero(param, sizeof (struct samr_LookupNames)); /* - * Windows NT returns NT_STATUS_NONE_MAPPED when the - * name is NULL. + * Windows NT returns NT_STATUS_NONE_MAPPED. * Windows 2000 returns STATUS_INVALID_ACCOUNT_NAME. */ - param->status = NT_SC_ERROR(NT_STATUS_NONE_MAPPED); + status = NT_STATUS_NONE_MAPPED; + } + + if (status != NT_STATUS_SUCCESS) { + bzero(param, sizeof (struct samr_LookupNames)); + param->status = NT_SC_ERROR(status); return (MLRPC_DRC_OK); } param->rids.rid = MLRPC_HEAP_NEW(mxa, DWORD); param->rid_types.rid_type = MLRPC_HEAP_NEW(mxa, DWORD); - if (desc->discrim == SAMR_BUILTIN_DOMAIN) { - sid = nt_builtin_lookup_name((char *)param->name.str, - &rid_type); + data = (samr_keydata_t *)hd->nh_data; - if (sid != 0) { + switch (data->kd_type) { + case NT_DOMAIN_BUILTIN: + wka = nt_builtin_lookup((char *)param->name.str); + if (wka != NULL) { param->rids.n_entry = 1; - (void) nt_sid_get_rid(sid, ¶m->rids.rid[0]); + (void) nt_sid_get_rid(wka->binsid, ¶m->rids.rid[0]); param->rid_types.n_entry = 1; - param->rid_types.rid_type[0] = rid_type; + param->rid_types.rid_type[0] = wka->sid_name_use; param->status = NT_STATUS_SUCCESS; - free(sid); return (MLRPC_DRC_OK); } - } else if (desc->discrim == SAMR_LOCAL_DOMAIN) { - grp = nt_group_getinfo((char *)param->name.str, RWLOCK_READER); + break; - if (grp != NULL) { + case NT_DOMAIN_LOCAL: + rc = smb_lgrp_getbyname((char *)param->name.str, &grp); + if (rc == SMB_LGRP_SUCCESS) { param->rids.n_entry = 1; - (void) nt_sid_get_rid(grp->sid, ¶m->rids.rid[0]); + param->rids.rid[0] = grp.sg_rid; param->rid_types.n_entry = 1; - param->rid_types.rid_type[0] = *grp->sid_name_use; + param->rid_types.rid_type[0] = grp.sg_id.gs_type; param->status = NT_STATUS_SUCCESS; - nt_group_putinfo(grp); + smb_lgrp_free(&grp); return (MLRPC_DRC_OK); } - if ((pw = getpwnam((const char *)param->name.str)) != NULL) { - param->rids.n_entry = 1; - param->rids.rid[0] = SAM_ENCODE_UXUID(pw->pw_uid); - param->rid_types.n_entry = 1; - param->rid_types.rid_type[0] = SidTypeUser; - param->status = NT_STATUS_SUCCESS; - return (MLRPC_DRC_OK); + if (smb_pwd_getpasswd((const char *)param->name.str, + &smbpw) != NULL) { + if (smb_idmap_getsid(smbpw.pw_uid, SMB_IDMAP_USER, + &sid) == IDMAP_SUCCESS) { + param->rids.n_entry = 1; + (void) nt_sid_get_rid(sid, ¶m->rids.rid[0]); + param->rid_types.n_entry = 1; + param->rid_types.rid_type[0] = SidTypeUser; + param->status = NT_STATUS_SUCCESS; + free(sid); + return (MLRPC_DRC_OK); + } } + break; - if ((gr = getgrnam((const char *)param->name.str)) != NULL) { - param->rids.n_entry = 1; - param->rids.rid[0] = SAM_ENCODE_UXGID(gr->gr_gid); - param->rid_types.n_entry = 1; - param->rid_types.rid_type[0] = SidTypeAlias; - param->status = NT_STATUS_SUCCESS; - return (MLRPC_DRC_OK); - } + default: + bzero(param, sizeof (struct samr_LookupNames)); + param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE); + return (MLRPC_DRC_OK); } param->rids.n_entry = 0; @@ -559,38 +608,44 @@ samr_s_LookupNames(void *arg, struct mlrpc_xaction *mxa) * obtained via a successful domain open request. The user is * specified by the rid in the request. */ -/*ARGSUSED*/ static int samr_s_OpenUser(void *arg, struct mlrpc_xaction *mxa) { struct samr_OpenUser *param = arg; - ms_handle_t *handle; + ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; + ndr_handle_t *hd; + samr_keydata_t *data; - if (!mlsvc_validate_handle( - (ms_handle_t *)¶m->handle, SAMR_DOMAIN_KEY)) { + if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) { bzero(¶m->user_handle, sizeof (samr_handle_t)); - param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED); + param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE); return (MLRPC_DRC_OK); } - handle = mlsvc_get_handle(MLSVC_IFSPEC_SAMR, SAMR_USER_KEY, - param->rid); - bcopy(handle, ¶m->user_handle, sizeof (samr_handle_t)); + data = (samr_keydata_t *)hd->nh_data; + + id = samr_hdalloc(mxa, SAMR_KEY_USER, data->kd_type, param->rid); + if (id == NULL) { + bzero(¶m->user_handle, sizeof (samr_handle_t)); + param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY); + } else { + bcopy(id, ¶m->user_handle, sizeof (samr_handle_t)); + /* + * Need QueryUserInfo(level 21). + */ + samr_hdfree(mxa, id); + bzero(¶m->user_handle, sizeof (samr_handle_t)); + param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED); + } - /* - * Need QueryUserInfo(level 21). - */ - bzero(¶m->user_handle, sizeof (samr_handle_t)); - param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED); return (MLRPC_DRC_OK); } /* * samr_s_DeleteUser * - * This is a request to delete a user within a specified domain in the - * local SAM database. The caller should supply a valid user handle but - * we deny access regardless. + * Request to delete a user within a specified domain in the local + * SAM database. The caller should supply a valid user handle. */ /*ARGSUSED*/ static int @@ -598,6 +653,7 @@ samr_s_DeleteUser(void *arg, struct mlrpc_xaction *mxa) { struct samr_DeleteUser *param = arg; + bzero(param, sizeof (struct samr_DeleteUser)); param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED); return (MLRPC_DRC_OK); } @@ -605,6 +661,8 @@ samr_s_DeleteUser(void *arg, struct mlrpc_xaction *mxa) /* * samr_s_QueryUserInfo * + * The caller should provide a valid user key. + * * Returns: * NT_STATUS_SUCCESS * NT_STATUS_ACCESS_DENIED @@ -616,60 +674,108 @@ samr_s_QueryUserInfo(void *arg, struct mlrpc_xaction *mxa) { struct samr_QueryUserInfo *param = arg; - if (!mlsvc_validate_handle( - (ms_handle_t *)¶m->user_handle, SAMR_USER_KEY)) { - bzero(param, sizeof (struct samr_QueryUserInfo)); - param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED); - return (MLRPC_DRC_OK); - } - bzero(param, sizeof (struct samr_QueryUserInfo)); - param->status = 0; + param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED); return (MLRPC_DRC_OK); } /* * samr_s_QueryUserGroups * - * This is a request to obtain a list of groups of which a user is a - * member. The user is identified from the handle, which contains an - * encoded uid in the discriminator field. - * - * Get complete list of groups and check for builtin domain. + * Request the list of groups of which a user is a member. + * The user is identified from the handle, which contains an + * rid in the discriminator field. Note that this is a local user. */ static int samr_s_QueryUserGroups(void *arg, struct mlrpc_xaction *mxa) { struct samr_QueryUserGroups *param = arg; struct samr_UserGroupInfo *info; - ms_handle_desc_t *desc; - struct passwd *pw; - DWORD uid; + struct samr_UserGroups *group; + ndr_hdid_t *id = (ndr_hdid_t *)¶m->user_handle; + ndr_handle_t *hd; + samr_keydata_t *data; + well_known_account_t *wka; + nt_sid_t *user_sid = NULL; + nt_sid_t *dom_sid; + smb_group_t grp; + smb_giter_t gi; + uint32_t status; + int size; + int ngrp_max; + + if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_USER)) == NULL) { + status = NT_STATUS_ACCESS_DENIED; + goto query_error; + } - desc = mlsvc_lookup_handle((ms_handle_t *)¶m->user_handle); - if (desc == 0 || strcmp(desc->key, SAMR_USER_KEY)) { - bzero(param, sizeof (struct samr_QueryUserGroups)); - param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED); - return (MLRPC_DRC_OK); + data = (samr_keydata_t *)hd->nh_data; + switch (data->kd_type) { + case NT_DOMAIN_BUILTIN: + wka = nt_builtin_lookup("builtin"); + if (wka == NULL) { + status = NT_STATUS_INTERNAL_ERROR; + goto query_error; + } + dom_sid = wka->binsid; + break; + case NT_DOMAIN_LOCAL: + dom_sid = nt_domain_local_sid(); + break; + default: + status = NT_STATUS_INVALID_HANDLE; + goto query_error; + } + + user_sid = nt_sid_splice(dom_sid, data->kd_rid); + if (user_sid == NULL) { + status = NT_STATUS_NO_MEMORY; + goto query_error; } info = MLRPC_HEAP_NEW(mxa, struct samr_UserGroupInfo); - info->groups = MLRPC_HEAP_NEW(mxa, struct samr_UserGroups); + if (info == NULL) { + status = NT_STATUS_NO_MEMORY; + goto query_error; + } + bzero(info, sizeof (struct samr_UserGroupInfo)); - uid = SAM_DECODE_RID(desc->discrim); + size = 32 * 1024; + info->groups = MLRPC_HEAP_MALLOC(mxa, size); + if (info->groups == NULL) { + status = NT_STATUS_NO_MEMORY; + goto query_error; + } + ngrp_max = size / sizeof (struct samr_UserGroups); - if ((pw = getpwuid(uid)) != 0) { - info->n_entry = 1; - info->groups->rid = SAM_ENCODE_UXGID(pw->pw_gid); - info->groups->attr = SE_GROUP_MANDATORY - | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_ENABLED; - param->info = info; - param->status = 0; - } else { - bzero(param, sizeof (struct samr_QueryUserGroups)); - param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED); + if (smb_lgrp_iteropen(&gi) != SMB_LGRP_SUCCESS) { + status = NT_STATUS_INTERNAL_ERROR; + goto query_error; } + info->n_entry = 0; + group = info->groups; + while ((info->n_entry < ngrp_max) && + (smb_lgrp_iterate(&gi, &grp) == SMB_LGRP_SUCCESS)) { + if (smb_lgrp_is_member(&grp, user_sid)) { + group->rid = grp.sg_rid; + group->attr = grp.sg_attr; + group++; + info->n_entry++; + } + smb_lgrp_free(&grp); + } + smb_lgrp_iterclose(&gi); + + free(user_sid); + param->info = info; + param->status = NT_STATUS_SUCCESS; + return (MLRPC_DRC_OK); + +query_error: + free(user_sid); + bzero(param, sizeof (struct samr_QueryUserGroups)); + param->status = NT_SC_ERROR(status); return (MLRPC_DRC_OK); } @@ -684,50 +790,59 @@ samr_s_QueryUserGroups(void *arg, struct mlrpc_xaction *mxa) * * We return a handle to be used to access information about this group. */ -/*ARGSUSED*/ static int samr_s_OpenGroup(void *arg, struct mlrpc_xaction *mxa) { struct samr_OpenGroup *param = arg; - ms_handle_t *handle; + ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; + ndr_handle_t *hd; + samr_keydata_t *data; - if (!mlsvc_validate_handle( - (ms_handle_t *)¶m->handle, SAMR_DOMAIN_KEY)) { + if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) { bzero(¶m->group_handle, sizeof (samr_handle_t)); - param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED); + param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE); return (MLRPC_DRC_OK); } - handle = mlsvc_get_handle(MLSVC_IFSPEC_SAMR, SAMR_GROUP_KEY, - param->rid); - bcopy(handle, ¶m->group_handle, sizeof (samr_handle_t)); + data = (samr_keydata_t *)hd->nh_data; + id = samr_hdalloc(mxa, SAMR_KEY_GROUP, data->kd_type, param->rid); + + if (id) { + bcopy(id, ¶m->group_handle, sizeof (samr_handle_t)); + param->status = 0; + } else { + bzero(¶m->group_handle, sizeof (samr_handle_t)); + param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY); + } - param->status = 0; return (MLRPC_DRC_OK); } /* * samr_s_Connect * - * This is a request to connect to the local SAM database. We don't - * support any form of update request and our database doesn't - * contain any private information, so there is little point in - * doing any access access checking here. + * This is a request to connect to the local SAM database. + * We don't support any form of update request and our database doesn't + * contain any private information, so there is little point in doing + * any access access checking here. * * Return a handle for use with subsequent SAM requests. */ -/*ARGSUSED*/ static int samr_s_Connect(void *arg, struct mlrpc_xaction *mxa) { struct samr_Connect *param = arg; - ms_handle_t *handle; + ndr_hdid_t *id; - handle = mlsvc_get_handle(MLSVC_IFSPEC_SAMR, - SAMR_CONNECT_KEY, SAMR_DATABASE_DOMAIN); - bcopy(handle, ¶m->handle, sizeof (samr_handle_t)); + id = samr_hdalloc(mxa, SAMR_KEY_CONNECT, NT_DOMAIN_NULL, 0); + if (id) { + bcopy(id, ¶m->handle, sizeof (samr_handle_t)); + param->status = 0; + } else { + bzero(¶m->handle, sizeof (samr_handle_t)); + param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY); + } - param->status = 0; return (MLRPC_DRC_OK); } @@ -741,24 +856,14 @@ static int samr_s_GetUserPwInfo(void *arg, struct mlrpc_xaction *mxa) { struct samr_GetUserPwInfo *param = arg; - ms_handle_t *handle; - DWORD status = 0; - - handle = (ms_handle_t *)¶m->user_handle; - - if (!mlsvc_validate_handle(handle, SAMR_USER_KEY)) - status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED); bzero(param, sizeof (struct samr_GetUserPwInfo)); - param->status = status; + param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED); return (MLRPC_DRC_OK); } /* * samr_s_CreateUser - * - * This is a request to create a user within a specified domain in the - * local SAM database. We always deny access. */ /*ARGSUSED*/ static int @@ -816,25 +921,25 @@ samr_s_SetUserInfo(void *arg, struct mlrpc_xaction *mxa) /* * samr_s_QueryDispInfo * - * This function is supposed to return local users' information. + * This function is supposed to return local user information. * As we don't support local users, this function dosen't send * back any information. * - * I added a peice of code that returns information for Administrator - * and Guest builtin users. All information are hard-coded which I get - * from packet captures. Currently, this peice of code is opt-out. + * Added template that returns information for Administrator and Guest + * builtin users. All information is hard-coded from packet captures. */ -/*ARGSUSED*/ static int samr_s_QueryDispInfo(void *arg, struct mlrpc_xaction *mxa) { struct samr_QueryDispInfo *param = arg; - ms_handle_desc_t *desc; + ndr_hdid_t *id = (ndr_hdid_t *)¶m->domain_handle; DWORD status = 0; - desc = mlsvc_lookup_handle((ms_handle_t *)¶m->domain_handle); - if (desc == NULL || (strcmp(desc->key, SAMR_DOMAIN_KEY) != 0)) - status = NT_STATUS_INVALID_HANDLE; + if (samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN) == NULL) { + bzero(param, sizeof (struct samr_QueryDispInfo)); + param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE); + return (MLRPC_DRC_OK); + } #ifdef SAMR_SUPPORT_USER if ((desc->discrim != SAMR_LOCAL_DOMAIN) || (param->start_idx != 0)) { @@ -897,24 +1002,21 @@ samr_s_QueryDispInfo(void *arg, struct mlrpc_xaction *mxa) * samr_s_EnumDomainGroups * * - * This function is supposed to return local users' information. + * This function is supposed to return local group information. * As we don't support local users, this function dosen't send * back any information. * - * I added a peice of code that returns information for a - * domain group as None. All information are hard-coded which I get - * from packet captures. Currently, this peice of code is opt-out. + * Added template that returns information for a domain group as None. + * All information is hard-coded from packet captures. */ -/*ARGSUSED*/ static int samr_s_EnumDomainGroups(void *arg, struct mlrpc_xaction *mxa) { struct samr_EnumDomainGroups *param = arg; - ms_handle_desc_t *desc; + ndr_hdid_t *id = (ndr_hdid_t *)¶m->domain_handle; DWORD status = NT_STATUS_SUCCESS; - desc = mlsvc_lookup_handle((ms_handle_t *)¶m->domain_handle); - if (desc == NULL || (strcmp(desc->key, SAMR_DOMAIN_KEY) != 0)) + if (samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN) == NULL) status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE); param->total_size = 0; @@ -964,18 +1066,17 @@ samr_s_EnumDomainGroups(void *arg, struct mlrpc_xaction *mxa) * for that alias. The alias domain sid should match with * the passed domain handle. */ -/*ARGSUSED*/ static int samr_s_OpenAlias(void *arg, struct mlrpc_xaction *mxa) { struct samr_OpenAlias *param = arg; - ms_handle_desc_t *desc = 0; - ms_handle_t *handle; - nt_group_t *grp; - DWORD status = NT_STATUS_SUCCESS; + ndr_hdid_t *id = (ndr_hdid_t *)¶m->domain_handle; + ndr_handle_t *hd; + uint32_t status; + samr_keydata_t *data; + int rc; - desc = mlsvc_lookup_handle((ms_handle_t *)¶m->domain_handle); - if (desc == 0 || (strcmp(desc->key, SAMR_DOMAIN_KEY) != 0)) { + if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) { status = NT_STATUS_INVALID_HANDLE; goto open_alias_err; } @@ -985,25 +1086,21 @@ samr_s_OpenAlias(void *arg, struct mlrpc_xaction *mxa) goto open_alias_err; } - grp = nt_groups_lookup_rid(param->rid); - if (grp == 0) { + data = (samr_keydata_t *)hd->nh_data; + rc = smb_lgrp_getbyrid(param->rid, (smb_gdomain_t)data->kd_type, NULL); + if (rc != SMB_LGRP_SUCCESS) { status = NT_STATUS_NO_SUCH_ALIAS; goto open_alias_err; } - if (((desc->discrim == SAMR_LOCAL_DOMAIN) && - !nt_sid_is_local(grp->sid)) || - ((desc->discrim == SAMR_BUILTIN_DOMAIN) && - !nt_sid_is_builtin(grp->sid))) { - status = NT_STATUS_NO_SUCH_ALIAS; - goto open_alias_err; + id = samr_hdalloc(mxa, SAMR_KEY_ALIAS, data->kd_type, param->rid); + if (id) { + bcopy(id, ¶m->alias_handle, sizeof (samr_handle_t)); + param->status = NT_STATUS_SUCCESS; + return (MLRPC_DRC_OK); } - handle = mlsvc_get_handle(MLSVC_IFSPEC_SAMR, SAMR_ALIAS_KEY, - param->rid); - bcopy(handle, ¶m->alias_handle, sizeof (samr_handle_t)); - param->status = 0; - return (MLRPC_DRC_OK); + status = NT_STATUS_NO_MEMORY; open_alias_err: bzero(¶m->alias_handle, sizeof (samr_handle_t)); @@ -1025,33 +1122,29 @@ static int samr_s_CreateDomainAlias(void *arg, struct mlrpc_xaction *mxa) { struct samr_CreateDomainAlias *param = arg; + ndr_hdid_t *id = (ndr_hdid_t *)¶m->alias_handle; + + if (samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN) == NULL) { + bzero(param, sizeof (struct samr_CreateDomainAlias)); + param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE); + return (MLRPC_DRC_OK); + } + + bzero(param, sizeof (struct samr_CreateDomainAlias)); + param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED); + return (MLRPC_DRC_OK); #ifdef SAMR_SUPPORT_ADD_ALIAS DWORD status = NT_STATUS_SUCCESS; - ms_handle_desc_t *desc = 0; - ms_handle_t *handle; nt_group_t *grp; char *alias_name; -#endif - bzero(¶m->alias_handle, sizeof (samr_handle_t)); - param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED); - return (MLRPC_DRC_OK); -#ifdef SAMR_SUPPORT_ADD_ALIAS alias_name = param->alias_name.str; if (alias_name == 0) { status = NT_STATUS_INVALID_PARAMETER; goto create_alias_err; } - desc = mlsvc_lookup_handle((ms_handle_t *)¶m->domain_handle); - if (desc == 0 || - (desc->discrim != SAMR_LOCAL_DOMAIN) || - (strcmp(desc->key, SAMR_DOMAIN_KEY) != 0)) { - status = NT_STATUS_INVALID_HANDLE; - goto create_alias_err; - } - /* * Check access mask. User should be member of * Administrators or Account Operators local group. @@ -1087,19 +1180,17 @@ create_alias_err: /* * samr_s_SetAliasInfo * - * For more information you can look at MSDN page for NetLocalGroupSetInfo. + * Similar to NetLocalGroupSetInfo. */ -/*ARGSUSED*/ static int samr_s_SetAliasInfo(void *arg, struct mlrpc_xaction *mxa) { struct samr_SetAliasInfo *param = arg; + ndr_hdid_t *id = (ndr_hdid_t *)¶m->alias_handle; DWORD status = NT_STATUS_SUCCESS; - if (!mlsvc_validate_handle( - (ms_handle_t *)¶m->alias_handle, SAMR_ALIAS_KEY)) { + if (samr_hdlookup(mxa, id, SAMR_KEY_ALIAS) == NULL) status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE); - } param->status = status; return (MLRPC_DRC_OK); @@ -1115,18 +1206,22 @@ static int samr_s_QueryAliasInfo(void *arg, struct mlrpc_xaction *mxa) { struct samr_QueryAliasInfo *param = arg; - ms_handle_desc_t *desc; - nt_group_t *grp; - DWORD status; + ndr_hdid_t *id = (ndr_hdid_t *)¶m->alias_handle; + ndr_handle_t *hd; + samr_keydata_t *data; + smb_group_t grp; + uint32_t status; + int rc; - desc = mlsvc_lookup_handle((ms_handle_t *)¶m->alias_handle); - if (desc == NULL || (strcmp(desc->key, SAMR_ALIAS_KEY) != 0)) { + if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_ALIAS)) == NULL) { status = NT_STATUS_INVALID_HANDLE; goto query_alias_err; } - grp = nt_groups_lookup_rid(desc->discrim); - if (grp == NULL) { + data = (samr_keydata_t *)hd->nh_data; + rc = smb_lgrp_getbyrid(data->kd_rid, (smb_gdomain_t)data->kd_type, + &grp); + if (rc != SMB_LGRP_SUCCESS) { status = NT_STATUS_NO_SUCH_ALIAS; goto query_alias_err; } @@ -1135,10 +1230,10 @@ samr_s_QueryAliasInfo(void *arg, struct mlrpc_xaction *mxa) case SAMR_QUERY_ALIAS_INFO_1: param->ru.info1.level = param->level; (void) mlsvc_string_save( - (ms_string_t *)¶m->ru.info1.name, grp->name, mxa); + (ms_string_t *)¶m->ru.info1.name, grp.sg_name, mxa); (void) mlsvc_string_save( - (ms_string_t *)¶m->ru.info1.desc, grp->comment, mxa); + (ms_string_t *)¶m->ru.info1.desc, grp.sg_cmnt, mxa); param->ru.info1.unknown = 1; break; @@ -1146,15 +1241,16 @@ samr_s_QueryAliasInfo(void *arg, struct mlrpc_xaction *mxa) case SAMR_QUERY_ALIAS_INFO_3: param->ru.info3.level = param->level; (void) mlsvc_string_save( - (ms_string_t *)¶m->ru.info3.desc, grp->comment, mxa); - + (ms_string_t *)¶m->ru.info3.desc, grp.sg_cmnt, mxa); break; default: + smb_lgrp_free(&grp); status = NT_STATUS_INVALID_INFO_CLASS; goto query_alias_err; }; + smb_lgrp_free(&grp); param->address = (DWORD)(uintptr_t)¶m->ru; param->status = 0; return (MLRPC_DRC_OK); @@ -1176,28 +1272,26 @@ query_alias_err: * This RPC is used by CMC and right now it returns access denied. * The peice of code that removes a local group doesn't get compiled. */ -/*ARGSUSED*/ static int samr_s_DeleteDomainAlias(void *arg, struct mlrpc_xaction *mxa) { struct samr_DeleteDomainAlias *param = arg; + ndr_hdid_t *id = (ndr_hdid_t *)¶m->alias_handle; -#ifdef SAMR_SUPPORT_DEL_ALIAS - ms_handle_desc_t *desc = 0; - nt_group_t *grp; - char *alias_name; - DWORD status; -#endif + if (samr_hdlookup(mxa, id, SAMR_KEY_ALIAS) == NULL) { + bzero(param, sizeof (struct samr_DeleteDomainAlias)); + param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE); + return (MLRPC_DRC_OK); + } + bzero(param, sizeof (struct samr_DeleteDomainAlias)); param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED); return (MLRPC_DRC_OK); #ifdef SAMR_SUPPORT_DEL_ALIAS - desc = mlsvc_lookup_handle((ms_handle_t *)¶m->alias_handle); - if (desc == 0 || (strcmp(desc->key, SAMR_ALIAS_KEY) != 0)) { - status = NT_STATUS_INVALID_HANDLE; - goto delete_alias_err; - } + nt_group_t *grp; + char *alias_name; + DWORD status; grp = nt_groups_lookup_rid(desc->discrim); if (grp == 0) { @@ -1234,77 +1328,65 @@ static int samr_s_EnumDomainAliases(void *arg, struct mlrpc_xaction *mxa) { struct samr_EnumDomainAliases *param = arg; - ms_handle_desc_t *desc; - nt_group_t *grp = NULL; - DWORD status; - nt_group_iterator_t *gi; - nt_sid_t *local_sid; - nt_sid_t *builtin_sid; - nt_sid_t *sid; - DWORD cnt, skip; + ndr_hdid_t *id = (ndr_hdid_t *)¶m->domain_handle; + ndr_handle_t *hd; + samr_keydata_t *data; + smb_group_t grp; + smb_giter_t gi; + int cnt, skip, i; struct name_rid *info; - desc = mlsvc_lookup_handle((ms_handle_t *)¶m->domain_handle); - if (desc == NULL || (strcmp(desc->key, SAMR_DOMAIN_KEY) != 0)) { - status = NT_STATUS_INVALID_HANDLE; - goto enum_alias_err; + if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) { + bzero(param, sizeof (struct samr_EnumDomainAliases)); + param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE); + return (MLRPC_DRC_OK); } - local_sid = nt_domain_local_sid(); - builtin_sid = nt_builtin_lookup_name("BUILTIN", 0); + data = (samr_keydata_t *)hd->nh_data; - if (desc->discrim == SAMR_LOCAL_DOMAIN) { - sid = local_sid; - } else if (desc->discrim == SAMR_BUILTIN_DOMAIN) { - sid = builtin_sid; - } else { - status = NT_STATUS_INVALID_HANDLE; - goto enum_alias_err; - } + (void) smb_lgrp_numbydomain((smb_gdomain_t)data->kd_type, &cnt); + if (cnt <= param->resume_handle) { + param->aliases = (struct aliases_info *)MLRPC_HEAP_MALLOC(mxa, + sizeof (struct aliases_info)); - cnt = skip = 0; - gi = nt_group_open_iterator(); - nt_group_ht_lock(RWLOCK_READER); - while ((grp = nt_group_iterate(gi)) != 0) { - if (skip++ < param->resume_handle) - continue; - if (nt_sid_is_indomain(sid, grp->sid)) - cnt++; + bzero(param->aliases, sizeof (struct aliases_info)); + param->out_resume = 0; + param->entries = 0; + param->status = NT_STATUS_SUCCESS; + return (MLRPC_DRC_OK); } - nt_group_ht_unlock(); - nt_group_close_iterator(gi); + cnt -= param->resume_handle; param->aliases = (struct aliases_info *)MLRPC_HEAP_MALLOC(mxa, sizeof (struct aliases_info) + (cnt-1) * sizeof (struct name_rid)); - param->aliases->count = cnt; - param->aliases->address = cnt; - info = param->aliases->info; + if (smb_lgrp_iteropen(&gi) != SMB_LGRP_SUCCESS) { + bzero(param, sizeof (struct samr_EnumDomainAliases)); + param->status = NT_SC_ERROR(NT_STATUS_INTERNAL_ERROR); + return (MLRPC_DRC_OK); + } - skip = 0; - gi = nt_group_open_iterator(); - nt_group_ht_lock(RWLOCK_READER); - while ((grp = nt_group_iterate(gi)) != NULL) { - if (skip++ < param->resume_handle) - continue; - if (nt_sid_is_indomain(sid, grp->sid)) { - (void) nt_sid_get_rid(grp->sid, &info->rid); + skip = i = 0; + info = param->aliases->info; + while (smb_lgrp_iterate(&gi, &grp) == SMB_LGRP_SUCCESS) { + if ((skip++ >= param->resume_handle) && + (grp.sg_domain == data->kd_type) && (i++ < cnt)) { + info->rid = grp.sg_rid; (void) mlsvc_string_save((ms_string_t *)&info->name, - grp->name, mxa); + grp.sg_name, mxa); info++; } + smb_lgrp_free(&grp); } - nt_group_ht_unlock(); - nt_group_close_iterator(gi); + smb_lgrp_iterclose(&gi); - param->out_resume = cnt; - param->entries = cnt; - param->status = 0; - return (MLRPC_DRC_OK); + param->aliases->count = i; + param->aliases->address = i; -enum_alias_err: - param->status = NT_SC_ERROR(status); + param->out_resume = i; + param->entries = i; + param->status = 0; return (MLRPC_DRC_OK); } diff --git a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_srvsvc.c b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_srvsvc.c index 26cd32ac5d..fbb37f5d04 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_srvsvc.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_srvsvc.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -100,21 +100,6 @@ static mlrpc_service_t srvsvc_service = { }; /* - * srvsvc_fix_comment - * - * The parser sometimes has problems with empty strings so we - * need to ensure that the comment field has something in it. - */ -static inline char * -srvsvc_fix_comment(char *original, char *alternative) -{ - if (original == 0 || strlen(original) == 0) - return (alternative); - - return (original); -} - -/* * srvsvc_share_mkpath * * Create the share path required by the share enum calls. This function @@ -516,12 +501,10 @@ srvsvc_s_NetShareSetInfo(void *arg, struct mlrpc_xaction *mxa) sizeof (DWORD)); param->parm_err = 0; - smb_config_rdlock(); - if (smb_config_getyorn(SMB_CI_SRVSVC_SHRSET_ENABLE) != 0) + if (!smb_config_getbool(SMB_CI_SRVSVC_SHRSET_ENABLE)) param->status = ERROR_SUCCESS; else param->status = ERROR_ACCESS_DENIED; - smb_config_unlock(); return (MLRPC_DRC_OK); } @@ -805,7 +788,7 @@ srvsvc_s_NetServerGetInfo(void *arg, struct mlrpc_xaction *mxa) struct mslm_SERVER_INFO_100 *info100; struct mslm_SERVER_INFO_101 *info101; struct mslm_SERVER_INFO_102 *info102; - char *sys_comment; + char sys_comment[SMB_PI_MAX_COMMENT]; char hostname[MAXHOSTNAMELEN]; if (smb_gethostname(hostname, MAXHOSTNAMELEN, 1) != 0) { @@ -814,10 +797,10 @@ netservergetinfo_no_memory: return (ERROR_NOT_ENOUGH_MEMORY); } - smb_config_rdlock(); - sys_comment = smb_config_getstr(SMB_CI_SYS_CMNT); - sys_comment = srvsvc_fix_comment(sys_comment, " "); - smb_config_unlock(); + (void) smb_config_getstr(SMB_CI_SYS_CMNT, sys_comment, + sizeof (sys_comment)); + if (*sys_comment == '\0') + (void) strcpy(sys_comment, " "); switch (param->level) { case 100: diff --git a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_svcctl.c b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_svcctl.c index eca831f899..242fdbc75f 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_svcctl.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_svcctl.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -43,17 +43,10 @@ #include <smbsrv/ndl/svcctl.ndl> /* - * SVCCTL diagnostics flag: set to 1 to enable verbose logging. + * The handle keys for this interface. */ -int svcctl_debug = 0; - -/* - * The handle keys for the various types of handles returned - * by this interface. - */ -#define SVCCTL_MANAGER_KEY "svcctlManager" -#define SVCCTL_SERVICE_KEY "svcctlService" - +static int svcctl_key_manager; +static int svcctl_key_service; typedef struct { char *svc_name; @@ -93,8 +86,6 @@ static svc_info_t svc_info[] = { static DWORD svcctl_get_status(const char *); static DWORD svcctl_validate_service(char *); -static DWORD svcctl_validate_handle(char *, ms_handle_t *, char *, - struct mlrpc_xaction *); static int svcctl_is_admin(struct mlrpc_xaction *); static int svcctl_s_Close(void *, struct mlrpc_xaction *); @@ -157,60 +148,51 @@ static int svcctl_s_Close(void *arg, struct mlrpc_xaction *mxa) { struct svcctl_Close *param = arg; - smb_dr_user_ctx_t *user_ctx = mxa->context->user_ctx; - ms_handle_t *handle; - DWORD status; + ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; - if (svcctl_debug) - smb_token_log(LOG_DEBUG, user_ctx, "(SvcctlClose)"); - - handle = (ms_handle_t *)¶m->handle; - status = svcctl_validate_handle("SvcctlClose", handle, 0, mxa); - - if (status == ERROR_SUCCESS) - (void) mlsvc_put_handle((ms_handle_t *)¶m->handle); + ndr_hdfree(mxa, id); bzero(¶m->result_handle, sizeof (svcctl_handle_t)); - param->status = status; + param->status = ERROR_SUCCESS; return (MLRPC_DRC_OK); } /* * svcctl_s_OpenManager * - * This is a request to open the service control manager. Dependent - * on the desired access we either generate a handle to be used on - * subsequent requests or deny access. + * Request to open the service control manager. + * The caller must have administrator rights in order to open this + * interface. We don't support write access. * * Returns: * ERROR_SUCCESS * ERROR_ACCESS_DENIED * - * Return a handle for use with subsequent svcctl requests. + * On success, returns a handle for use with subsequent svcctl requests. */ static int svcctl_s_OpenManager(void *arg, struct mlrpc_xaction *mxa) { struct svcctl_OpenManager *param = arg; - ms_handle_t *handle; + ndr_hdid_t *id; int rc; rc = svcctl_is_admin(mxa); if ((rc == 0) || (param->desired_access & SC_MANAGER_LOCK) != 0) { - /* - * The user doesn't have Administrator rights - * or wants a write lock on the Services DB. - */ bzero(¶m->handle, sizeof (svcctl_handle_t)); param->status = ERROR_ACCESS_DENIED; return (MLRPC_DRC_OK); } - handle = mlsvc_get_handle(MLSVC_IFSPEC_SVCCTL, SVCCTL_MANAGER_KEY, 0); - bcopy(handle, ¶m->handle, sizeof (svcctl_handle_t)); + if ((id = ndr_hdalloc(mxa, &svcctl_key_manager)) != NULL) { + bcopy(id, ¶m->handle, sizeof (svcctl_handle_t)); + param->status = ERROR_SUCCESS; + } else { + bzero(¶m->handle, sizeof (svcctl_handle_t)); + param->status = ERROR_ACCESS_DENIED; + } - param->status = ERROR_SUCCESS; return (MLRPC_DRC_OK); } @@ -228,15 +210,14 @@ static int svcctl_s_OpenService(void *arg, struct mlrpc_xaction *mxa) { struct svcctl_OpenService *param = arg; - ms_handle_t *handle; + ndr_hdid_t *id = (ndr_hdid_t *)¶m->manager_handle; + ndr_handle_t *hd; DWORD status; - status = svcctl_validate_handle("SvcctlOpenService", - (ms_handle_t *)¶m->manager_handle, SVCCTL_MANAGER_KEY, mxa); - - if (status != ERROR_SUCCESS) { + hd = ndr_hdlookup(mxa, id); + if ((hd == NULL) || (hd->nh_data != &svcctl_key_manager)) { bzero(¶m->service_handle, sizeof (svcctl_handle_t)); - param->status = status; + param->status = ERROR_INVALID_HANDLE; return (MLRPC_DRC_OK); } @@ -247,10 +228,14 @@ svcctl_s_OpenService(void *arg, struct mlrpc_xaction *mxa) return (MLRPC_DRC_OK); } - handle = mlsvc_get_handle(MLSVC_IFSPEC_SVCCTL, SVCCTL_SERVICE_KEY, 0); - bcopy(handle, ¶m->service_handle, sizeof (svcctl_handle_t)); + if ((id = ndr_hdalloc(mxa, &svcctl_key_service)) != NULL) { + bcopy(id, ¶m->service_handle, sizeof (svcctl_handle_t)); + param->status = ERROR_SUCCESS; + } else { + bzero(¶m->service_handle, sizeof (svcctl_handle_t)); + param->status = ERROR_ACCESS_DENIED; + } - param->status = ERROR_SUCCESS; return (MLRPC_DRC_OK); } @@ -265,14 +250,13 @@ static int svcctl_s_QueryServiceStatus(void *arg, struct mlrpc_xaction *mxa) { struct svcctl_QueryServiceStatus *param = arg; - DWORD status; - - status = svcctl_validate_handle("SvcctlQueryServiceStatus", - (ms_handle_t *)¶m->service_handle, SVCCTL_SERVICE_KEY, mxa); + ndr_hdid_t *id = (ndr_hdid_t *)¶m->service_handle; + ndr_handle_t *hd; - if (status != ERROR_SUCCESS) { + hd = ndr_hdlookup(mxa, id); + if ((hd == NULL) || (hd->nh_data != &svcctl_key_service)) { bzero(¶m, sizeof (struct svcctl_QueryServiceStatus)); - param->status = status; + param->status = ERROR_INVALID_HANDLE; return (MLRPC_DRC_OK); } @@ -303,19 +287,19 @@ static int svcctl_s_EnumServicesStatus(void *arg, struct mlrpc_xaction *mxa) { struct svcctl_EnumServicesStatus *param = arg; + ndr_hdid_t *id = (ndr_hdid_t *)¶m->manager_handle; + ndr_handle_t *hd; svc_enum_status_t *service_table; svc_enum_status_t *svc; mts_wchar_t *wide_name; char *name; int i, namelen; int offs; - DWORD status; - status = svcctl_validate_handle("SvcctlEnumServicesStatus", - (ms_handle_t *)¶m->manager_handle, SVCCTL_MANAGER_KEY, mxa); - - if (status != ERROR_SUCCESS) { - param->status = status; + hd = ndr_hdlookup(mxa, id); + if ((hd == NULL) || (hd->nh_data != &svcctl_key_manager)) { + bzero(¶m, sizeof (struct svcctl_EnumServicesStatus)); + param->status = ERROR_INVALID_HANDLE; return (MLRPC_DRC_OK); } @@ -382,14 +366,13 @@ static int svcctl_s_QueryServiceConfig(void *arg, struct mlrpc_xaction *mxa) { struct svcctl_QueryServiceConfig *param = arg; - DWORD status; - - status = svcctl_validate_handle("SvcctlQueryServiceConfig", - (ms_handle_t *)¶m->service_handle, SVCCTL_SERVICE_KEY, mxa); + ndr_hdid_t *id = (ndr_hdid_t *)¶m->service_handle; + ndr_handle_t *hd; - if (status != ERROR_SUCCESS) { + hd = ndr_hdlookup(mxa, id); + if ((hd == NULL) || (hd->nh_data != &svcctl_key_service)) { bzero(¶m, sizeof (struct svcctl_QueryServiceConfig)); - param->status = status; + param->status = ERROR_INVALID_HANDLE; return (MLRPC_DRC_OK); } @@ -434,30 +417,6 @@ svcctl_validate_service(char *svc_name) } /* - * Check whether or not the svcctl module allocated this handle. - * - * Returns: - * ERROR_SUCCESS - * ERROR_INVALID_HANDLE. - */ -/*ARGSUSED*/ -static DWORD -svcctl_validate_handle(char *name, ms_handle_t *handle, char *key, - struct mlrpc_xaction *mxa) -{ - int mgr_erc; - int svc_erc; - - mgr_erc = mlsvc_validate_handle(handle, SVCCTL_MANAGER_KEY); - svc_erc = mlsvc_validate_handle(handle, SVCCTL_SERVICE_KEY); - - if (mgr_erc == 0 && svc_erc == 0) - return (ERROR_INVALID_HANDLE); - - return (ERROR_SUCCESS); -} - -/* * Report the service status: SERVICE_PAUSED or SERVICE_RUNNING. */ /*ARGSUSED*/ diff --git a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_util.c b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_util.c index 81e3893781..94f50d40b4 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_util.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_util.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -35,8 +35,6 @@ #include <unistd.h> #include <netdb.h> #include <stdlib.h> -#include <pwd.h> -#include <grp.h> #include <sys/time.h> #include <sys/systm.h> @@ -53,15 +51,14 @@ #include <smbsrv/mlsvc_util.h> #include <smbsrv/mlsvc.h> +/* Domain join support (using MS-RPC) */ +static boolean_t mlsvc_ntjoin_support = B_FALSE; + 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); extern int mlsvc_user_getauth(char *, char *, smb_auth_info_t *); -static int mlsvc_lookup_local_name(char *name, nt_sid_t **sid); -static int mlsvc_lookup_nt_name(char *name, nt_sid_t **sid); -static int mlsvc_lookup_nt_sid(nt_sid_t *sid, char *buf, int bufsize); - /* * Compare the supplied domain name with the local hostname. * We need to deal with both server names and fully-qualified @@ -77,9 +74,11 @@ int mlsvc_is_local_domain(const char *domain) { char hostname[MAXHOSTNAMELEN]; - uint32_t mode; int rc; + if (smb_config_get_secmode() == SMB_SECMODE_WORKGRP) + return (1); + if (strchr(domain, '.') != NULL) rc = smb_getfqhostname(hostname, MAXHOSTNAMELEN); else @@ -88,10 +87,7 @@ mlsvc_is_local_domain(const char *domain) if (rc != 0) return (-1); - rc = strcasecmp(domain, hostname); - mode = smb_get_security_mode(); - - if ((rc == 0) || (mode == SMB_SECMODE_WORKGRP)) + if (strcasecmp(domain, hostname) == 0) return (1); return (0); @@ -100,163 +96,62 @@ mlsvc_is_local_domain(const char *domain) /* * mlsvc_lookup_name * - * Lookup a name in the specified domain and translate it to a SID. - * If the name is in the NT domain, it may refer to a user, group or - * alias. Otherwise it must refer to a UNIX username. The memory for - * the sid is allocated using malloc so the caller should call free - * when it is no longer required. - * - * On success, 0 will be returned and sid will point to a local domain - * user SID. Otherwise -1 will be returned. - */ -int -mlsvc_lookup_name(char *domain, char *name, nt_sid_t **sid) -{ - if (domain == NULL || name == NULL || sid == NULL) - return (-1); - - if (mlsvc_is_local_domain(domain) == 1) - return (mlsvc_lookup_local_name(name, sid)); - else - return (mlsvc_lookup_nt_name(name, sid)); -} - -/* - * mlsvc_lookup_local_name - * - * Lookup a name in the local password file and translate it to a SID. - * The name must refer to a user. This is a private function intended - * to support mlsvc_lookup_name so it doesn't perform any parameter - * validation. The memory for the sid is allocated using malloc so the - * caller must call free when it is no longer required. - * - * On success, 0 will be returned and sid will point to a local domain - * user SID. Otherwise -1 will be returned. - */ -static int -mlsvc_lookup_local_name(char *name, nt_sid_t **sid) -{ - struct passwd *pw; - nt_sid_t *domain_sid; - - if ((pw = getpwnam(name)) == NULL) - return (-1); - - if ((domain_sid = nt_domain_local_sid()) == NULL) - return (-1); - - *sid = nt_sid_splice(domain_sid, pw->pw_uid); - return (0); -} - -/* - * mlsvc_lookup_nt_name - * - * Lookup a name in the specified NT domain and translate it to a SID. - * The name may refer to a user, group or alias. This is a private - * function intended to support mlsvc_lookup_name so it doesn't do any - * parameter validation. The memory for the sid is allocated using - * malloc so the caller should call free when it is no longer required. + * This is just a wrapper for lsa_lookup_name. * - * On success, 0 will be returned and sid will point to an NT domain - * user SID. Otherwise -1 will be returned. + * The memory for the sid is allocated using malloc so the caller should + * call free when it is no longer required. */ -static int -mlsvc_lookup_nt_name(char *name, nt_sid_t **sid) +uint32_t +mlsvc_lookup_name(char *account, nt_sid_t **sid, uint16_t *sid_type) { - smb_userinfo_t *user_info; + smb_userinfo_t *ainfo; + uint32_t status; - if ((user_info = mlsvc_alloc_user_info()) == NULL) - return (-1); + if ((ainfo = mlsvc_alloc_user_info()) == NULL) + return (NT_STATUS_NO_MEMORY); - if (lsa_lookup_name(0, 0, name, user_info) != 0) - return (-1); + status = lsa_lookup_name(NULL, account, *sid_type, ainfo); + if (status == NT_STATUS_SUCCESS) { + *sid = ainfo->user_sid; + ainfo->user_sid = NULL; + *sid_type = ainfo->sid_name_use; + } - *sid = nt_sid_splice(user_info->domain_sid, user_info->rid); - mlsvc_free_user_info(user_info); - return (0); + mlsvc_free_user_info(ainfo); + return (status); } /* * mlsvc_lookup_sid * - * Lookup a SID and translate it to a name. The name returned may refer - * to a domain, user, group or alias dependent on the SID. On success 0 - * will be returned. Otherwise -1 will be returned. + * This is just a wrapper for lsa_lookup_sid. + * + * The allocated memory for the returned name must be freed by caller upon + * successful return. */ -int -mlsvc_lookup_sid(nt_sid_t *sid, char *buf, int bufsize) +uint32_t +mlsvc_lookup_sid(nt_sid_t *sid, char **name) { - struct passwd *pw; - struct group *gr; - nt_group_t *grp; - DWORD rid; - - if (sid == NULL || buf == NULL) - return (-1); - - if (nt_sid_is_local(sid)) { - (void) nt_sid_get_rid(sid, &rid); - - switch (SAM_RID_TYPE(rid)) { - case SAM_RT_NT_UID: - break; - - case SAM_RT_NT_GID: - if ((grp = nt_groups_lookup_rid(rid)) == NULL) - return (-1); - - (void) strlcpy(buf, grp->name, bufsize); - break; - - case SAM_RT_UNIX_UID: - if ((pw = getpwuid(SAM_DECODE_RID(rid))) == NULL) - return (-1); + smb_userinfo_t *ainfo; + uint32_t status; + int namelen; - (void) strlcpy(buf, pw->pw_name, bufsize); - break; + if ((ainfo = mlsvc_alloc_user_info()) == NULL) + return (NT_STATUS_NO_MEMORY); - case SAM_RT_UNIX_GID: - if ((gr = getgrgid(SAM_DECODE_RID(rid))) == NULL) - return (-1); - - (void) strlcpy(buf, gr->gr_name, bufsize); - break; + status = lsa_lookup_sid(sid, ainfo); + if (status == NT_STATUS_SUCCESS) { + namelen = strlen(ainfo->domain_name) + strlen(ainfo->name) + 2; + if ((*name = malloc(namelen)) == NULL) { + mlsvc_free_user_info(ainfo); + return (NT_STATUS_NO_MEMORY); } - - return (0); + (void) snprintf(*name, namelen, "%s\\%s", + ainfo->domain_name, ainfo->name); } - return (mlsvc_lookup_nt_sid(sid, buf, bufsize)); -} - -/* - * mlsvc_lookup_nt_sid - * - * Lookup an NT SID and translate it to a name. This is a private - * function intended to support mlsvc_lookup_sid so it doesn't do any - * parameter validation. The input account_name specifies the logon/ - * session to be used for the lookup. It doesn't need to have any - * association with the SID being looked up. The name returned may - * refer to a domain, user, group or alias dependent on the SID. - * - * On success the name will be copied into buf and 0 will be returned. - * Otherwise -1 will be returned. - */ -static int -mlsvc_lookup_nt_sid(nt_sid_t *sid, char *buf, int bufsize) -{ - smb_userinfo_t *user_info; - int rc; - - if ((user_info = mlsvc_alloc_user_info()) == NULL) - return (-1); - - if ((rc = lsa_lookup_sid(sid, user_info)) == 0) - (void) strlcpy(buf, user_info->name, bufsize); - - mlsvc_free_user_info(user_info); - return (rc); + mlsvc_free_user_info(ainfo); + return (status); } /* @@ -337,8 +232,8 @@ void mlsvc_setadmin_user_info(smb_userinfo_t *user_info) { nt_domain_t *domain; - nt_group_t *grp; - int i; + smb_group_t grp; + int rc, i; if ((domain = nt_domain_lookupbytype(NT_DOMAIN_PRIMARY)) == NULL) return; @@ -356,12 +251,11 @@ mlsvc_setadmin_user_info(smb_userinfo_t *user_info) user_info->flags |= SMB_UINFO_FLAG_DADMIN; } - grp = nt_group_getinfo("Administrators", RWLOCK_READER); - if (grp) { - i = nt_group_is_member(grp, user_info->user_sid); - nt_group_putinfo(grp); - if (i) + rc = smb_lgrp_getbyname("Administrators", &grp); + if (rc == SMB_LGRP_SUCCESS) { + if (smb_lgrp_is_member(&grp, user_info->user_sid)) user_info->flags |= SMB_UINFO_FLAG_LADMIN; + smb_lgrp_free(&grp); } } @@ -447,6 +341,7 @@ mlsvc_join(char *server, char *domain, char *plain_user, char *plain_text) DWORD status; mlsvc_handle_t netr_handle; char machine_passwd[MLSVC_MACHINE_ACCT_PASSWD_MAX]; + char fqdn[MAXHOSTNAMELEN]; machine_passwd[0] = '\0'; @@ -472,14 +367,13 @@ mlsvc_join(char *server, char *domain, char *plain_user, char *plain_text) erc = mlsvc_logon(server, domain, plain_user); if (erc == AUTH_USER_GRANT) { - int isenabled; - - smb_config_rdlock(); - isenabled = smb_config_getyorn(SMB_CI_ADS_ENABLE); - smb_config_unlock(); - if (isenabled) { - if (ads_join(plain_user, plain_text, machine_passwd, - sizeof (machine_passwd)) == ADJOIN_SUCCESS) + if (mlsvc_ntjoin_support == B_FALSE) { + if (smb_resolve_fqdn(domain, fqdn, MAXHOSTNAMELEN) != 1) + return (NT_STATUS_INVALID_PARAMETER); + + if (ads_join(fqdn, plain_user, plain_text, + machine_passwd, sizeof (machine_passwd)) + == ADJOIN_SUCCESS) status = NT_STATUS_SUCCESS; else status = NT_STATUS_UNSUCCESSFUL; @@ -500,7 +394,9 @@ mlsvc_join(char *server, char *domain, char *plain_user, char *plain_text) } if (status == NT_STATUS_SUCCESS) { - if (smb_set_machine_pwd(machine_passwd) != 0) + erc = smb_config_setstr(SMB_CI_MACHINE_PASSWD, + machine_passwd); + if (erc != SMBD_SMF_OK) return (NT_STATUS_UNSUCCESSFUL); /* @@ -509,7 +405,7 @@ mlsvc_join(char *server, char *domain, char *plain_user, char *plain_text) * that we use the SAMLOGON version of the NETLOGON * PDC location protocol. */ - smb_set_domain_member(1); + (void) smb_config_setbool(SMB_CI_DOMAIN_MEMB, B_TRUE); if (netr_open(server, domain, &netr_handle) == 0) { status = netlogon_auth(server, &netr_handle, @@ -525,197 +421,3 @@ mlsvc_join(char *server, char *domain, char *plain_user, char *plain_text) return (status); } - -/*ARGSUSED*/ -void -nt_group_ht_lock(krwmode_t locktype) -{ -} - -void -nt_group_ht_unlock(void) -{ -} - -int -nt_group_num_groups(void) -{ - return (0); -} - -/*ARGSUSED*/ -uint32_t -nt_group_add(char *gname, char *comment) -{ - return (NT_STATUS_NOT_SUPPORTED); -} - -/*ARGSUSED*/ -uint32_t -nt_group_modify(char *gname, char *new_gname, char *comment) -{ - return (NT_STATUS_NOT_SUPPORTED); -} - -/*ARGSUSED*/ -uint32_t -nt_group_delete(char *gname) -{ - return (NT_STATUS_NOT_SUPPORTED); -} - -/*ARGSUSED*/ -nt_group_t * -nt_group_getinfo(char *gname, krwmode_t locktype) -{ - return (NULL); -} - -/*ARGSUSED*/ -void -nt_group_putinfo(nt_group_t *grp) -{ -} - -/*ARGSUSED*/ -int -nt_group_getpriv(nt_group_t *grp, uint32_t priv_id) -{ - return (SE_PRIVILEGE_DISABLED); -} - -/*ARGSUSED*/ -uint32_t -nt_group_setpriv(nt_group_t *grp, uint32_t priv_id, uint32_t new_attr) -{ - return (NT_STATUS_NOT_SUPPORTED); -} - -/*ARGSUSED*/ -int -nt_group_is_member(nt_group_t *grp, nt_sid_t *sid) -{ - return (0); -} - -/*ARGSUSED*/ -uint32_t -nt_group_add_member(nt_group_t *grp, nt_sid_t *msid, uint16_t sid_name_use, - char *account) -{ - return (NT_STATUS_NOT_SUPPORTED); -} - -/*ARGSUSED*/ -uint32_t -nt_group_del_member(nt_group_t *grp, void *key, int keytype) -{ - return (NT_STATUS_NOT_SUPPORTED); -} - -/*ARGSUSED*/ -int -nt_group_num_members(nt_group_t *grp) -{ - return (0); -} - -nt_group_iterator_t * -nt_group_open_iterator(void) -{ - return (NULL); -} - -/*ARGSUSED*/ -void -nt_group_close_iterator(nt_group_iterator_t *gi) -{ -} - -/*ARGSUSED*/ -nt_group_t * -nt_group_iterate(nt_group_iterator_t *gi) -{ - return (NULL); -} - -int -nt_group_cache_size(void) -{ - return (0); -} - -uint32_t -sam_init(void) -{ - return (NT_STATUS_SUCCESS); -} - -/*ARGSUSED*/ -uint32_t -nt_group_add_member_byname(char *gname, char *account) -{ - return (NT_STATUS_NOT_SUPPORTED); -} - -/*ARGSUSED*/ -uint32_t -nt_group_del_member_byname(nt_group_t *grp, char *member_name) -{ - return (NT_STATUS_NOT_SUPPORTED); -} - -/*ARGSUSED*/ -void -nt_group_add_groupprivs(nt_group_t *grp, smb_privset_t *priv) -{ -} - -/*ARGSUSED*/ -uint32_t -nt_groups_member_privs(nt_sid_t *sid, smb_privset_t *priv) -{ - return (NT_STATUS_SUCCESS); -} - -/*ARGSUSED*/ -int -nt_groups_member_ngroups(nt_sid_t *sid) -{ - return (0); -} - -/*ARGSUSED*/ -uint32_t -nt_groups_member_groups(nt_sid_t *sid, smb_id_t *grps, int ngrps) -{ - return (NT_STATUS_SUCCESS); -} - -/*ARGSUSED*/ -nt_group_t * -nt_groups_lookup_rid(uint32_t rid) -{ - return (NULL); -} - -/*ARGSUSED*/ -int -nt_groups_count(int cnt_opt) -{ - return (0); -} - -/*ARGSUSED*/ -int -nt_group_member_list(int offset, nt_group_t *grp, - ntgrp_member_list_t *rmembers) -{ - return (0); -} - -/*ARGSUSED*/ -void -nt_group_list(int offset, char *pattern, ntgrp_list_t *list) -{ -} diff --git a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_winreg.c b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_winreg.c index 9dd5696526..9d017b57e1 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_winreg.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_winreg.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -45,11 +45,12 @@ #include <smbsrv/ndl/winreg.ndl> /* - * List of mlsvc handle (local handle management) keys. + * Local handle management keys. */ -#define WINREG_HKLM "WinregOpenHKLM" -#define WINREG_HKU "WinregOpenUser" -#define WINREG_KEY "WinregOpenKey" +static int winreg_hk; +static int winreg_hklm; +static int winreg_hkuser; +static int winreg_hkkey; /* * List of supported registry keys (case-insensitive). @@ -62,29 +63,41 @@ static char *winreg_keys[] = { static char *winreg_lookup_value(const char *); +static int winreg_s_OpenHK(void *, struct mlrpc_xaction *); static int winreg_s_OpenHKLM(void *, struct mlrpc_xaction *); static int winreg_s_OpenHKUsers(void *, struct mlrpc_xaction *); static int winreg_s_Close(void *, struct mlrpc_xaction *); static int winreg_s_CreateKey(void *, struct mlrpc_xaction *); static int winreg_s_DeleteKey(void *, struct mlrpc_xaction *); static int winreg_s_DeleteValue(void *, struct mlrpc_xaction *); +static int winreg_s_FlushKey(void *, struct mlrpc_xaction *); +static int winreg_s_GetKeySec(void *, struct mlrpc_xaction *); +static int winreg_s_NotifyChange(void *, struct mlrpc_xaction *); static int winreg_s_OpenKey(void *, struct mlrpc_xaction *); static int winreg_s_QueryKey(void *, struct mlrpc_xaction *); static int winreg_s_QueryValue(void *, struct mlrpc_xaction *); +static int winreg_s_SetKeySec(void *, struct mlrpc_xaction *); static int winreg_s_CreateValue(void *, struct mlrpc_xaction *); static int winreg_s_Shutdown(void *, struct mlrpc_xaction *); static int winreg_s_GetVersion(void *, struct mlrpc_xaction *); static mlrpc_stub_table_t winreg_stub_table[] = { + { winreg_s_OpenHK, WINREG_OPNUM_OpenHKCR }, + { winreg_s_OpenHK, WINREG_OPNUM_OpenHKCU }, { winreg_s_OpenHKLM, WINREG_OPNUM_OpenHKLM }, + { winreg_s_OpenHK, WINREG_OPNUM_OpenHKPD }, { winreg_s_OpenHKUsers, WINREG_OPNUM_OpenHKUsers }, { winreg_s_Close, WINREG_OPNUM_Close }, { winreg_s_CreateKey, WINREG_OPNUM_CreateKey }, { winreg_s_DeleteKey, WINREG_OPNUM_DeleteKey }, { winreg_s_DeleteValue, WINREG_OPNUM_DeleteValue }, + { winreg_s_FlushKey, WINREG_OPNUM_FlushKey }, + { winreg_s_GetKeySec, WINREG_OPNUM_GetKeySec }, + { winreg_s_NotifyChange, WINREG_OPNUM_NotifyChange }, { winreg_s_OpenKey, WINREG_OPNUM_OpenKey }, { winreg_s_QueryKey, WINREG_OPNUM_QueryKey }, { winreg_s_QueryValue, WINREG_OPNUM_QueryValue }, + { winreg_s_SetKeySec, WINREG_OPNUM_SetKeySec }, { winreg_s_CreateValue, WINREG_OPNUM_CreateValue }, { winreg_s_Shutdown, WINREG_OPNUM_Shutdown }, { winreg_s_GetVersion, WINREG_OPNUM_GetVersion }, @@ -131,28 +144,48 @@ winreg_initialize(void) } /* + * winreg_s_OpenHK + * + * Stub. + */ +static int +winreg_s_OpenHK(void *arg, struct mlrpc_xaction *mxa) +{ + struct winreg_OpenHKCR *param = arg; + ndr_hdid_t *id; + + if ((id = ndr_hdalloc(mxa, &winreg_hk)) == NULL) { + bzero(¶m->handle, sizeof (winreg_handle_t)); + param->status = ERROR_ACCESS_DENIED; + } else { + bcopy(id, ¶m->handle, sizeof (winreg_handle_t)); + param->status = ERROR_SUCCESS; + } + + return (MLRPC_DRC_OK); +} + +/* * winreg_s_OpenHKLM * - * This is a request to open the HKLM and get a handle. The client - * should treat the handle as an opaque object. + * This is a request to open the HKLM and get a handle. + * The client should treat the handle as an opaque object. * * Status: * ERROR_SUCCESS Valid handle returned. * ERROR_ACCESS_DENIED Unable to allocate a handle. */ -/*ARGSUSED*/ static int winreg_s_OpenHKLM(void *arg, struct mlrpc_xaction *mxa) { - struct msreg_OpenHKLM *param = arg; - ms_handle_t *handle; + struct winreg_OpenHKLM *param = arg; + ndr_hdid_t *id; - handle = mlsvc_get_handle(MLSVC_IFSPEC_WINREG, WINREG_HKLM, 0); - if (handle == NULL) { - bzero(¶m->handle, sizeof (msreg_handle_t)); + if ((id = ndr_hdalloc(mxa, &winreg_hklm)) == NULL) { + bzero(¶m->handle, sizeof (winreg_handle_t)); param->status = ERROR_ACCESS_DENIED; } else { - bcopy(handle, ¶m->handle, sizeof (msreg_handle_t)); + bcopy(id, ¶m->handle, sizeof (winreg_handle_t)); param->status = ERROR_SUCCESS; } @@ -167,19 +200,17 @@ winreg_s_OpenHKLM(void *arg, struct mlrpc_xaction *mxa) * to support subsequent requests, but we may support enough now. It * seems okay with regedt32. */ -/*ARGSUSED*/ static int winreg_s_OpenHKUsers(void *arg, struct mlrpc_xaction *mxa) { - struct msreg_OpenHKUsers *param = arg; - ms_handle_t *handle; + struct winreg_OpenHKUsers *param = arg; + ndr_hdid_t *id; - handle = mlsvc_get_handle(MLSVC_IFSPEC_WINREG, WINREG_HKU, 0); - if (handle == NULL) { - bzero(¶m->handle, sizeof (msreg_handle_t)); + if ((id = ndr_hdalloc(mxa, &winreg_hkuser)) == NULL) { + bzero(¶m->handle, sizeof (winreg_handle_t)); param->status = ERROR_ACCESS_DENIED; } else { - bcopy(handle, ¶m->handle, sizeof (msreg_handle_t)); + bcopy(id, ¶m->handle, sizeof (winreg_handle_t)); param->status = ERROR_SUCCESS; } @@ -194,14 +225,15 @@ winreg_s_OpenHKUsers(void *arg, struct mlrpc_xaction *mxa) * and return MLRPC_DRC_OK. Setting the handle to zero appears to be * standard behaviour. */ -/*ARGSUSED*/ static int winreg_s_Close(void *arg, struct mlrpc_xaction *mxa) { - struct msreg_Close *param = arg; + struct winreg_Close *param = arg; + ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; - (void) mlsvc_put_handle((ms_handle_t *)¶m->handle); - bzero(¶m->result_handle, sizeof (msreg_handle_t)); + ndr_hdfree(mxa, id); + + bzero(¶m->result_handle, sizeof (winreg_handle_t)); param->status = ERROR_SUCCESS; return (MLRPC_DRC_OK); } @@ -213,7 +245,7 @@ winreg_s_Close(void *arg, struct mlrpc_xaction *mxa) static int winreg_s_CreateKey(void *arg, struct mlrpc_xaction *mxa) { - struct msreg_CreateKey *param = arg; + struct winreg_CreateKey *param = arg; param->status = ERROR_ACCESS_DENIED; return (MLRPC_DRC_OK); @@ -226,7 +258,7 @@ winreg_s_CreateKey(void *arg, struct mlrpc_xaction *mxa) static int winreg_s_DeleteKey(void *arg, struct mlrpc_xaction *mxa) { - struct msreg_DeleteKey *param = arg; + struct winreg_DeleteKey *param = arg; param->status = ERROR_ACCESS_DENIED; return (MLRPC_DRC_OK); @@ -239,13 +271,53 @@ winreg_s_DeleteKey(void *arg, struct mlrpc_xaction *mxa) static int winreg_s_DeleteValue(void *arg, struct mlrpc_xaction *mxa) { - struct msreg_DeleteValue *param = arg; + struct winreg_DeleteValue *param = arg; param->status = ERROR_ACCESS_DENIED; return (MLRPC_DRC_OK); } /* + * winreg_s_FlushKey + */ +/*ARGSUSED*/ +static int +winreg_s_FlushKey(void *arg, struct mlrpc_xaction *mxa) +{ + struct winreg_FlushKey *param = arg; + + param->status = ERROR_SUCCESS; + return (MLRPC_DRC_OK); +} + +/* + * winreg_s_GetKeySec + */ +/*ARGSUSED*/ +static int +winreg_s_GetKeySec(void *arg, struct mlrpc_xaction *mxa) +{ + struct winreg_GetKeySec *param = arg; + + bzero(param, sizeof (struct winreg_GetKeySec)); + param->status = ERROR_SUCCESS; + return (MLRPC_DRC_OK); +} + +/* + * winreg_s_NotifyChange + */ +/*ARGSUSED*/ +static int +winreg_s_NotifyChange(void *arg, struct mlrpc_xaction *mxa) +{ + struct winreg_NotifyChange *param = arg; + + param->status = ERROR_SUCCESS; + return (MLRPC_DRC_OK); +} + +/* * winreg_s_OpenKey * * This is a request to open a windows registry key. The list @@ -256,33 +328,29 @@ winreg_s_DeleteValue(void *arg, struct mlrpc_xaction *mxa) * ERROR_SUCCESS Valid handle returned. * ERROR_FILE_NOT_FOUND No key or unable to allocate a handle. */ -/*ARGSUSED*/ static int winreg_s_OpenKey(void *arg, struct mlrpc_xaction *mxa) { - struct msreg_OpenKey *param = arg; - ms_handle_t *handle; + struct winreg_OpenKey *param = arg; char *key = (char *)param->name.str; + ndr_hdid_t *id = NULL; int i; for (i = 0; i < sizeof (winreg_keys)/sizeof (winreg_keys[0]); ++i) { if (strcasecmp(key, winreg_keys[i]) == 0) { - handle = mlsvc_get_handle(MLSVC_IFSPEC_WINREG, - WINREG_KEY, 0); - - if (handle == NULL) - break; - - bcopy(handle, ¶m->result_handle, - sizeof (msreg_handle_t)); - - param->status = ERROR_SUCCESS; - return (MLRPC_DRC_OK); + id = ndr_hdalloc(mxa, &winreg_hkkey); + break; } } - bzero(¶m->result_handle, sizeof (msreg_handle_t)); - param->status = ERROR_FILE_NOT_FOUND; + if (id == NULL) { + bzero(¶m->result_handle, sizeof (winreg_handle_t)); + param->status = ERROR_FILE_NOT_FOUND; + } else { + bcopy(id, ¶m->result_handle, sizeof (winreg_handle_t)); + param->status = ERROR_SUCCESS; + } + return (MLRPC_DRC_OK); } @@ -294,9 +362,9 @@ static int winreg_s_QueryKey(void *arg, struct mlrpc_xaction *mxa) { static char nullstr[2] = { 0, 0 }; - struct msreg_QueryKey *param = arg; + struct winreg_QueryKey *param = arg; - bzero(param, sizeof (struct msreg_QueryKey)); + bzero(param, sizeof (struct winreg_QueryKey)); param->name.length = 2; param->name.allosize = 0; @@ -311,15 +379,15 @@ winreg_s_QueryKey(void *arg, struct mlrpc_xaction *mxa) * This is a request to get the value associated with a specified name. * * Returns: - * ERROR_SUCCESS Value returned. + * ERROR_SUCCESS Value returned. * ERROR_FILE_NOT_FOUND PrimaryModule is not supported. * ERROR_CANTREAD No such name or memory problem. */ static int winreg_s_QueryValue(void *arg, struct mlrpc_xaction *mxa) { - struct msreg_QueryValue *param = arg; - struct msreg_value *pv; + struct winreg_QueryValue *param = arg; + struct winreg_value *pv; char *name; char *value; DWORD slen; @@ -338,9 +406,9 @@ winreg_s_QueryValue(void *arg, struct mlrpc_xaction *mxa) } slen = mts_wcequiv_strlen(value) + sizeof (mts_wchar_t); - msize = sizeof (struct msreg_value) + slen; + msize = sizeof (struct winreg_value) + slen; - param->value = (struct msreg_value *)MLRPC_HEAP_MALLOC(mxa, msize); + param->value = (struct winreg_value *)MLRPC_HEAP_MALLOC(mxa, msize); param->type = MLRPC_HEAP_NEW(mxa, DWORD); param->value_size = MLRPC_HEAP_NEW(mxa, DWORD); param->value_size_total = MLRPC_HEAP_NEW(mxa, DWORD); @@ -408,13 +476,26 @@ winreg_lookup_value(const char *name) } /* + * winreg_s_SetKeySec + */ +/*ARGSUSED*/ +static int +winreg_s_SetKeySec(void *arg, struct mlrpc_xaction *mxa) +{ + struct winreg_SetKeySec *param = arg; + + param->status = ERROR_ACCESS_DENIED; + return (MLRPC_DRC_OK); +} + +/* * winreg_s_CreateValue */ /*ARGSUSED*/ static int winreg_s_CreateValue(void *arg, struct mlrpc_xaction *mxa) { - struct msreg_CreateValue *param = arg; + struct winreg_CreateValue *param = arg; param->status = ERROR_ACCESS_DENIED; return (MLRPC_DRC_OK); @@ -429,7 +510,7 @@ winreg_s_CreateValue(void *arg, struct mlrpc_xaction *mxa) static int winreg_s_Shutdown(void *arg, struct mlrpc_xaction *mxa) { - struct msreg_Shutdown *param = arg; + struct winreg_Shutdown *param = arg; param->status = ERROR_ACCESS_DENIED; return (MLRPC_DRC_OK); @@ -446,7 +527,7 @@ winreg_s_Shutdown(void *arg, struct mlrpc_xaction *mxa) static int winreg_s_GetVersion(void *arg, struct mlrpc_xaction *mxa) { - struct msreg_GetVersion *param = arg; + struct winreg_GetVersion *param = arg; param->version = 5; param->status = ERROR_SUCCESS; diff --git a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_wkssvc.c b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_wkssvc.c index b7453b171e..294acef207 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_wkssvc.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_wkssvc.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -84,7 +84,7 @@ wkssvc_s_NetWkstaGetInfo(void *arg, struct mlrpc_xaction *mxa) struct mslm_NetWkstaGetInfo *param = arg; mslm_NetWkstaGetInfo_rb *rb; char hostname[MAXHOSTNAMELEN]; - char *resource_domain; + char resource_domain[SMB_PI_MAX_DOMAIN]; char *p; DWORD status; int rc; @@ -113,16 +113,12 @@ wkssvc_s_NetWkstaGetInfo(void *arg, struct mlrpc_xaction *mxa) } rb->buf100.wki100_computername = (unsigned char *)p; - smb_config_rdlock(); - resource_domain = smb_config_getstr(SMB_CI_DOMAIN_NAME); - + (void) smb_getdomainname(resource_domain, SMB_PI_MAX_DOMAIN); if ((p = MLRPC_HEAP_STRSAVE(mxa, resource_domain)) == NULL) { - smb_config_unlock(); status = ERROR_NOT_ENOUGH_MEMORY; break; } - smb_config_unlock(); rb->buf100.wki100_langroup = (unsigned char *)p; status = ERROR_SUCCESS; break; diff --git a/usr/src/lib/smbsrv/libmlsvc/common/netr_auth.c b/usr/src/lib/smbsrv/libmlsvc/common/netr_auth.c index 1b26087fb8..c385d837b8 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/netr_auth.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/netr_auth.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -292,7 +292,6 @@ netr_gen_session_key(netr_info_t *netr_info) DWORD *client_challenge; DWORD *server_challenge; int rc; - char *machine_passwd; DWORD le_data[2]; client_challenge = (DWORD *)(uintptr_t)&netr_info->client_challenge; @@ -304,20 +303,15 @@ netr_gen_session_key(netr_info_t *netr_info) * the appropriate password but it isn't working yet. So we * always use the default one for now. */ - smb_config_rdlock(); - machine_passwd = smb_config_getstr(SMB_CI_MACHINE_PASSWD); + bzero(netr_info->password, sizeof (netr_info->password)); + rc = smb_config_getstr(SMB_CI_MACHINE_PASSWD, + (char *)netr_info->password, sizeof (netr_info->password)); - if (!machine_passwd || *machine_passwd == 0) { - smb_config_unlock(); + if ((rc != SMBD_SMF_OK) || *netr_info->password == '\0') { return (-1); } - bzero(netr_info->password, sizeof (netr_info->password)); - (void) strlcpy((char *)netr_info->password, (char *)machine_passwd, - sizeof (netr_info->password)); - - rc = smb_auth_ntlm_hash((char *)machine_passwd, md4hash); - smb_config_unlock(); + rc = smb_auth_ntlm_hash((char *)netr_info->password, md4hash); if (rc != SMBAUTH_SUCCESS) return (SMBAUTH_FAILURE); diff --git a/usr/src/lib/smbsrv/libmlsvc/common/netr_logon.c b/usr/src/lib/smbsrv/libmlsvc/common/netr_logon.c index 93079001e9..152d97cd85 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/netr_logon.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/netr_logon.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -38,6 +38,7 @@ #include <netdb.h> #include <smbsrv/libsmb.h> +#include <smbsrv/libsmbrdr.h> #include <smbsrv/ndl/netlogon.ndl> #include <smbsrv/mlsvc_util.h> #include <smbsrv/mlsvc.h> @@ -94,32 +95,18 @@ netlogon_logon(netr_client_t *clnt, smb_userinfo_t *user_info) DWORD status; int retries = 0; - smb_config_rdlock(); - (void) strlcpy(resource_domain, smb_config_getstr(SMB_CI_DOMAIN_NAME), - sizeof (resource_domain)); - smb_config_unlock(); + (void) smb_getdomainname(resource_domain, SMB_PI_MAX_DOMAIN); - /* - * If the SMB info cache is not valid, - * try to locate a domain controller. - */ - if ((di = smb_getdomaininfo(0)) == NULL) { - (void) mlsvc_locate_domain_controller(resource_domain); - - if ((di = smb_getdomaininfo(0)) == NULL) - return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO); - } + if ((di = smb_getdomaininfo(0)) == NULL) + return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO); if ((mlsvc_echo(di->server)) < 0) { /* * We had a session to the DC but it's not responding. - * So drop the credential chain and find another DC. + * So drop the credential chain. */ netr_invalidate_chain(); - (void) mlsvc_locate_domain_controller(resource_domain); - - if ((di = smb_getdomaininfo(0)) == NULL) - return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO); + return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO); } do { diff --git a/usr/src/lib/smbsrv/libmlsvc/common/samlib.c b/usr/src/lib/smbsrv/libmlsvc/common/samlib.c index ef303a8b21..1e8e533721 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/samlib.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/samlib.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -50,99 +50,6 @@ #define SAM_KEYLEN 16 extern DWORD samr_set_user_info(mlsvc_handle_t *, smb_auth_info_t *); -static int get_user_group_info(mlsvc_handle_t *, smb_userinfo_t *); - -/* - * sam_lookup_user_info - * - * Lookup user information in the SAM database on the specified server - * (domain controller). The LSA interface is used to obtain the user - * RID, the domain name and the domain SID (user privileges are TBD). - * Then the various SAM layers are opened using the domain SID and the - * user RID to obtain the users's group membership information. - * - * The information is returned in the user_info structure. The caller - * is responsible for allocating and releasing this structure. If the - * lookup is successful, sid_name_use will be set to SidTypeUser. - * - * On success 0 is returned. Otherwise a -ve error code. - */ -int -sam_lookup_user_info(char *server, char *domain_name, - char *account_name, smb_userinfo_t *user_info) -{ - mlsvc_handle_t samr_handle; - mlsvc_handle_t domain_handle; - mlsvc_handle_t user_handle; - struct samr_sid *sid; - int rc; - DWORD access_mask; - DWORD status; - - if (lsa_lookup_name(server, domain_name, account_name, user_info) != 0) - return (-1); - - if (user_info->sid_name_use != SidTypeUser || - user_info->rid == 0 || user_info->domain_sid == 0) { - return (-1); - } - - rc = samr_open(server, domain_name, account_name, - SAM_LOOKUP_INFORMATION, &samr_handle); - if (rc != 0) - return (-1); - sid = (struct samr_sid *)user_info->domain_sid; - - status = samr_open_domain(&samr_handle, SAM_LOOKUP_INFORMATION, - sid, &domain_handle); - if (status == 0) { - access_mask = STANDARD_RIGHTS_EXECUTE | SAM_ACCESS_USER_READ; - - status = samr_open_user(&domain_handle, access_mask, - user_info->rid, &user_handle); - - if (status == NT_STATUS_SUCCESS) { - (void) get_user_group_info(&user_handle, user_info); - (void) samr_close_handle(&user_handle); - } else { - rc = -1; - } - - (void) samr_close_handle(&domain_handle); - } else { - rc = -1; - } - - (void) samr_close_handle(&samr_handle); - return (rc); -} - -/* - * get_user_group_info - * - * This is a private function to obtain the primary group and group - * memberships for the user specified by the user_handle. This function - * should only be called from sam_lookup_user_info. - * - * On success 0 is returned. Otherwise -1 is returned. - */ -static int -get_user_group_info(mlsvc_handle_t *user_handle, smb_userinfo_t *user_info) -{ - union samr_user_info sui; - int rc; - - rc = samr_query_user_info(user_handle, SAMR_QUERY_USER_GROUPRID, &sui); - if (rc != 0) - return (-1); - - rc = samr_query_user_groups(user_handle, user_info); - if (rc != 0) - return (-1); - - user_info->primary_group_rid = sui.info9.group_rid; - return (0); -} /* * sam_create_trust_account @@ -157,7 +64,6 @@ get_user_group_info(mlsvc_handle_t *user_handle, smb_userinfo_t *user_info) DWORD sam_create_trust_account(char *server, char *domain, smb_auth_info_t *auth) { - smb_userinfo_t *user_info; char account_name[MAXHOSTNAMELEN]; DWORD status; @@ -166,19 +72,13 @@ sam_create_trust_account(char *server, char *domain, smb_auth_info_t *auth) (void) strlcat(account_name, "$", MAXHOSTNAMELEN); - if ((user_info = mlsvc_alloc_user_info()) == 0) - return (NT_STATUS_NO_MEMORY); - /* * The trust account value here should match * the value that will be used when the user * information is set on this account. */ status = sam_create_account(server, domain, account_name, - auth, SAMR_AF_WORKSTATION_TRUST_ACCOUNT, user_info); - - mlsvc_free_user_info(user_info); - + auth, SAMR_AF_WORKSTATION_TRUST_ACCOUNT); /* * Based on network traces, a Windows 2000 client will @@ -209,11 +109,12 @@ sam_create_trust_account(char *server, char *domain, smb_auth_info_t *auth) */ DWORD sam_create_account(char *server, char *domain_name, char *account_name, - smb_auth_info_t *auth, DWORD account_flags, smb_userinfo_t *user_info) + smb_auth_info_t *auth, DWORD account_flags) { mlsvc_handle_t samr_handle; mlsvc_handle_t domain_handle; mlsvc_handle_t user_handle; + smb_userinfo_t *user_info; union samr_user_info sui; struct samr_sid *sid; DWORD rid; @@ -221,6 +122,9 @@ sam_create_account(char *server, char *domain_name, char *account_name, int rc; char *user = smbrdr_ipc_get_user(); + if ((user_info = mlsvc_alloc_user_info()) == 0) + return (NT_STATUS_NO_MEMORY); + rc = samr_open(server, domain_name, user, SAM_CONNECT_CREATE_ACCOUNT, &samr_handle); @@ -228,6 +132,7 @@ sam_create_account(char *server, char *domain_name, char *account_name, status = NT_STATUS_OPEN_FAILED; smb_tracef("SamCreateAccount[%s\\%s]: %s", domain_name, account_name, xlate_nt_status(status)); + mlsvc_free_user_info(user_info); return (status); } @@ -242,6 +147,7 @@ sam_create_account(char *server, char *domain_name, char *account_name, smb_tracef("SamCreateAccount[%s\\%s]: %s", domain_name, account_name, xlate_nt_status(status)); + mlsvc_free_user_info(user_info); return (status); } } @@ -254,6 +160,7 @@ sam_create_account(char *server, char *domain_name, char *account_name, smb_tracef("SamCreateAccount[%s]: lookup failed", account_name); + mlsvc_free_user_info(user_info); return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO); } @@ -274,14 +181,7 @@ sam_create_account(char *server, char *domain_name, char *account_name, (void) samr_get_user_pwinfo(&user_handle); (void) samr_set_user_info(&user_handle, auth); (void) samr_close_handle(&user_handle); - } else if (status == NT_STATUS_USER_EXISTS) { - mlsvc_release_user_info(user_info); - - rc = lsa_lookup_name(server, domain_name, account_name, - user_info); - if (rc == 0) - rid = user_info->rid; - } else { + } else if (status != NT_STATUS_USER_EXISTS) { smb_tracef("SamCreateAccount[%s]: %s", account_name, xlate_nt_status(status)); } @@ -294,6 +194,7 @@ sam_create_account(char *server, char *domain_name, char *account_name, } (void) samr_close_handle(&samr_handle); + mlsvc_free_user_info(user_info); return (status); } diff --git a/usr/src/lib/smbsrv/libmlsvc/common/samr_lookup.c b/usr/src/lib/smbsrv/libmlsvc/common/samr_lookup.c index e20b6404d7..463cd7f223 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/samr_lookup.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/samr_lookup.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -473,7 +473,7 @@ samr_set_user_unknowns(struct samr_SetUserInfo23 *info) info->sd.length = 0; info->sd.data = 0; info->user_rid = 0; - info->group_rid = MLSVC_DOMAIN_GROUP_RID_USERS; + info->group_rid = DOMAIN_GROUP_RID_USERS; /* * The trust account value used here should probably diff --git a/usr/src/lib/smbsrv/libmlsvc/common/samr_open.c b/usr/src/lib/smbsrv/libmlsvc/common/samr_open.c index 233acdf84d..015165798f 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/samr_open.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/samr_open.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -318,7 +318,7 @@ samr_connect4(char *server, char *domain, char *username, DWORD access_mask, { struct samr_Connect4 arg; mlrpc_heapref_t heapref; - char *dns_name; + char dns_name[MAXHOSTNAMELEN]; int len; int opnum; DWORD status; @@ -327,9 +327,10 @@ samr_connect4(char *server, char *domain, char *username, DWORD access_mask, opnum = SAMR_OPNUM_Connect; status = NT_STATUS_SUCCESS; + if (smb_resolve_fqdn(domain, dns_name, MAXHOSTNAMELEN) != 1) + return (NT_STATUS_UNSUCCESSFUL); + (void) mlsvc_rpc_init(&heapref); - dns_name = mlrpc_heap_malloc(heapref.heap, MAXHOSTNAMELEN); - (void) smb_getdomainname(dns_name, MAXHOSTNAMELEN); if (strlen(dns_name) > 0) { len = strlen(server) + strlen(dns_name) + 4; diff --git a/usr/src/lib/smbsrv/libmlsvc/common/secdb.c b/usr/src/lib/smbsrv/libmlsvc/common/secdb.c index cc4d96456f..1c46a89504 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/secdb.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/secdb.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -338,23 +338,36 @@ static smb_privset_t * smb_token_create_privs(smb_userinfo_t *user_info) { smb_privset_t *privs; - nt_group_t *grp; + smb_giter_t gi; + smb_group_t grp; + int rc; privs = smb_privset_new(); if (privs == NULL) return (NULL); - (void) nt_groups_member_privs(user_info->user_sid, privs); + if (smb_lgrp_iteropen(&gi) != SMB_LGRP_SUCCESS) { + smb_privset_free(privs); + return (NULL); + } + + while (smb_lgrp_iterate(&gi, &grp) == SMB_LGRP_SUCCESS) { + if (smb_lgrp_is_member(&grp, user_info->user_sid)) { + smb_privset_merge(privs, grp.sg_privs); + } + smb_lgrp_free(&grp); + } + smb_lgrp_iterclose(&gi); if (user_info->flags & SMB_UINFO_FLAG_ADMIN) { - grp = nt_group_getinfo("Administrators", RWLOCK_READER); - if (grp) { - nt_group_add_groupprivs(grp, privs); - nt_group_putinfo(grp); + rc = smb_lgrp_getbyname("Administrators", &grp); + if (rc == SMB_LGRP_SUCCESS) { + smb_privset_merge(privs, grp.sg_privs); + smb_lgrp_free(&grp); } /* - * This privilege is required for view/edit of SACL + * This privilege is required to view/edit SACL */ smb_privset_enable(privs, SE_SECURITY_LUID); } @@ -513,6 +526,8 @@ smb_token_create_wingrps(smb_userinfo_t *user_info) smb_rid_attrs_t *g_grps; smb_sid_attrs_t *grp; nt_sid_t *builtin_sid; + smb_giter_t gi; + smb_group_t lgrp; uint32_t n_gg, n_lg, n_dlg, n_wg; uint32_t i, j; int size, count; @@ -524,7 +539,7 @@ smb_token_create_wingrps(smb_userinfo_t *user_info) n_dlg = user_info->n_other_grps; /* Domain Local Groups */ /* Local Groups */ - n_lg = nt_groups_member_ngroups(user_info->user_sid); + (void) smb_lgrp_numbymember(user_info->user_sid, (int *)&n_lg); /* Well known Groups */ if ((user_info->flags & SMB_UINFO_FLAG_ADMIN) == SMB_UINFO_FLAG_DADMIN) @@ -538,20 +553,18 @@ smb_token_create_wingrps(smb_userinfo_t *user_info) count = n_gg + n_dlg + n_lg + n_wg; size = sizeof (smb_win_grps_t) + (count * sizeof (smb_id_t)); - tkn_grps = (smb_win_grps_t *)malloc(size); - if (tkn_grps == NULL) { + if ((tkn_grps = malloc(size)) == NULL) return (NULL); - } bzero(tkn_grps, size); - tkn_grps->wg_count = count; - /* Add global groups */ g_grps = user_info->groups; - for (i = 0; i < n_gg; ++i) { + for (i = 0; i < n_gg; i++) { grp = &tkn_grps->wg_groups[i].i_sidattr; - grp->attrs = g_grps[i].attributes; grp->sid = nt_sid_splice(user_info->domain_sid, g_grps[i].rid); + if (grp->sid == NULL) + break; + grp->attrs = g_grps[i].attributes; } if (n_gg == 0) { @@ -559,34 +572,55 @@ smb_token_create_wingrps(smb_userinfo_t *user_info) * if there's no global group should add the * primary group. */ - grp = &tkn_grps->wg_groups[i++].i_sidattr; - grp->attrs = 0x7; + grp = &tkn_grps->wg_groups[i].i_sidattr; grp->sid = nt_sid_dup(user_info->pgrp_sid); - tkn_grps->wg_count++; + if (grp->sid != NULL) { + grp->attrs = 0x7; + i++; + } } /* Add domain local groups */ dlg_grps = user_info->other_grps; - for (j = 0; j < n_dlg; ++j, ++i) { + for (j = 0; j < n_dlg; j++, i++) { grp = &tkn_grps->wg_groups[i].i_sidattr; - grp->attrs = dlg_grps[j].attrs; grp->sid = nt_sid_dup(dlg_grps[j].sid); + if (grp->sid == NULL) + break; + grp->attrs = dlg_grps[j].attrs; } - if (n_lg) { - /* Add local groups */ - (void) nt_groups_member_groups(user_info->user_sid, - &tkn_grps->wg_groups[i], n_lg); - i += n_lg; + /* Add local groups */ + if (n_lg && (smb_lgrp_iteropen(&gi) == SMB_LGRP_SUCCESS)) { + j = 0; + while (smb_lgrp_iterate(&gi, &lgrp) == SMB_LGRP_SUCCESS) { + if ((j < n_lg) && + smb_lgrp_is_member(&lgrp, user_info->user_sid)) { + grp = &tkn_grps->wg_groups[i].i_sidattr; + grp->sid = nt_sid_dup(lgrp.sg_id.gs_sid); + if (grp->sid == NULL) { + smb_lgrp_free(&lgrp); + break; + } + grp->attrs = lgrp.sg_attr; + i++; + j++; + } + smb_lgrp_free(&lgrp); + } + smb_lgrp_iterclose(&gi); } /* Add well known groups */ - for (j = 0; j < n_wg; ++j, ++i) { + for (j = 0; j < n_wg; j++, i++) { builtin_sid = nt_builtin_lookup_name(wk_grps[j], NULL); + if (builtin_sid == NULL) + break; tkn_grps->wg_groups[i].i_sidattr.sid = builtin_sid; tkn_grps->wg_groups[i].i_sidattr.attrs = 0x7; } + tkn_grps->wg_count = i; return (tkn_grps); } @@ -698,6 +732,7 @@ smb_logon_local(netr_client_t *clnt, smb_userinfo_t *uinfo) &smbpw, clnt->lm_password.lm_password_val, clnt->lm_password.lm_password_len, + clnt->domain, clnt->username); } @@ -708,6 +743,7 @@ smb_logon_local(netr_client_t *clnt, smb_userinfo_t *uinfo) &smbpw, clnt->nt_password.nt_password_val, clnt->nt_password.nt_password_len, + clnt->domain, clnt->username); } @@ -747,7 +783,7 @@ smb_setup_luinfo(smb_userinfo_t *lui, netr_client_t *clnt, uid_t uid) idmap_stat stat; smb_idmap_batch_t sib; smb_idmap_t *umap, *gmap; - nt_group_t *grp; + smb_group_t grp; struct passwd pw; char pwbuf[1024]; @@ -820,11 +856,10 @@ smb_setup_luinfo(smb_userinfo_t *lui, netr_client_t *clnt, uid_t uid) if ((lui->user_sid == NULL) || (lui->pgrp_sid == NULL)) return (NT_STATUS_NO_MEMORY); - grp = nt_group_getinfo("Administrators", RWLOCK_READER); - if (grp) { - if (nt_group_is_member(grp, lui->user_sid)) + if (smb_lgrp_getbyname("Administrators", &grp) == SMB_LGRP_SUCCESS) { + if (smb_lgrp_is_member(&grp, lui->user_sid)) lui->flags = SMB_UINFO_FLAG_LADMIN; - nt_group_putinfo(grp); + smb_lgrp_free(&grp); } return (NT_STATUS_SUCCESS); diff --git a/usr/src/lib/smbsrv/libmlsvc/common/smb_autohome.c b/usr/src/lib/smbsrv/libmlsvc/common/smb_autohome.c index 6d0610add3..bc3f526046 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/smb_autohome.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/smb_autohome.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -224,8 +224,9 @@ void smb_autohome_setent(void) { smb_autohome_info_t *si; - char *mappath; + char path[MAXNAMELEN]; char filename[MAXNAMELEN]; + int rc; if ((si = smb_autohome_getinfo()) != 0) { (void) fseek(si->fp, 0L, SEEK_SET); @@ -236,12 +237,12 @@ smb_autohome_setent(void) if ((si = &smb_ai) == 0) return; - smb_config_rdlock(); - if ((mappath = smb_config_get(SMB_CI_AUTOHOME_MAP)) == NULL) - mappath = SMB_AUTOHOME_PATH; - (void) snprintf(filename, MAXNAMELEN, "%s/%s", mappath, + rc = smb_config_getstr(SMB_CI_AUTOHOME_MAP, path, sizeof (path)); + if (rc != SMBD_SMF_OK) + return; + + (void) snprintf(filename, MAXNAMELEN, "%s/%s", path, SMB_AUTOHOME_FILE); - smb_config_unlock(); if ((si->fp = fopen(filename, "r")) == NULL) return; diff --git a/usr/src/lib/smbsrv/libsmb/Makefile.com b/usr/src/lib/smbsrv/libsmb/Makefile.com index 3771f7d993..857605eb72 100644 --- a/usr/src/lib/smbsrv/libsmb/Makefile.com +++ b/usr/src/lib/smbsrv/libsmb/Makefile.com @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -56,11 +56,10 @@ OBJS_COMMON = \ smb_door_encdec.o \ smb_doorclnt.o \ smb_downcalls.o \ - smb_group_door_encdec.o \ - smb_group_xdr.o \ smb_ht.o \ smb_idmap.o \ smb_info.o \ + smb_lgrp.o \ smb_mac.o \ smb_pwdutil.o \ smb_privilege.o \ @@ -77,7 +76,7 @@ include ../../Makefile.lib INCS += -I$(SRC)/common/smbsrv LDLIBS += $(MACH_LDLIBS) -LDLIBS += -lscf -lmd -lnsl -lpkcs11 -lc -lidmap +LDLIBS += -lscf -lmd -lnsl -lpkcs11 -lc -lresolv -lidmap CPPFLAGS += $(INCS) -D_REENTRANT SRCS= $(OBJS_COMMON:%.o=$(SRCDIR)/%.c) \ diff --git a/usr/src/lib/smbsrv/libsmb/amd64/Makefile b/usr/src/lib/smbsrv/libsmb/amd64/Makefile index b3c4916b0c..03c6ea5b61 100644 --- a/usr/src/lib/smbsrv/libsmb/amd64/Makefile +++ b/usr/src/lib/smbsrv/libsmb/amd64/Makefile @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" diff --git a/usr/src/lib/smbsrv/libsmb/common/libsmb.h b/usr/src/lib/smbsrv/libsmb/common/libsmb.h index 510f68c20d..50a3c3d989 100644 --- a/usr/src/lib/smbsrv/libsmb/common/libsmb.h +++ b/usr/src/lib/smbsrv/libsmb/common/libsmb.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -34,11 +34,14 @@ extern "C" { #include <sys/types.h> #include <arpa/inet.h> +#include <netdb.h> #include <stdlib.h> #include <libscf.h> #include <libshare.h> +#include <sqlite/sqlite.h> +#include <smbsrv/string.h> #include <smbsrv/smb_idmap.h> /* @@ -67,7 +70,6 @@ extern "C" { /* Max value length of all SMB properties */ #define MAX_VALUE_BUFLEN 512 -#define SMB_PI_MAX_DOMAIN_U 48 #define SMBD_FMRI_PREFIX "network/smb/server" #define SMBD_DEFAULT_INSTANCE_FMRI "svc:/network/smb/server:default" @@ -78,6 +80,7 @@ extern "C" { #define SMBD_SMF_NO_MEMORY 1 /* no memory for data structures */ #define SMBD_SMF_SYSTEM_ERR 2 /* system error, use errno */ #define SMBD_SMF_NO_PERMISSION 3 /* no permission for operation */ +#define SMBD_SMF_INVALID_ARG 4 #define SCH_STATE_UNINIT 0 #define SCH_STATE_INITIALIZING 1 @@ -99,72 +102,8 @@ typedef struct smb_scfhandle { /* * CIFS Configuration Management */ - -/* macros for the description of all config params */ -#define SMB_CD_RDR_IPCMODE "rdr_ipcmode" -#define SMB_CD_RDR_IPCUSER "rdr_ipcuser" -#define SMB_CD_RDR_IPCPWD "rdr_ipcpasswd" - -#define SMB_CD_OPLOCK_ENABLE "oplock_enable" -#define SMB_CD_OPLOCK_TIMEOUT "oplock_timeout" - -#define SMB_CD_AUTOHOME_MAP "autohome_map" - -#define SMB_CD_DOMAIN_SID "domain_sid" -#define SMB_CD_DOMAIN_MEMB "domain_member" -#define SMB_CD_DOMAIN_NAME "domain_name" -#define SMB_CD_DOMAIN_SRV "pdc" - -#define SMB_CD_WINS_SRV1 "wins_server_1" -#define SMB_CD_WINS_SRV2 "wins_server_2" -#define SMB_CD_WINS_EXCL "wins_exclude" - -#define SMB_CD_SRVSVC_SHRSET_ENABLE "srvsvc_sharesetinfo_enable" -#define SMB_CD_LOGR_ENABLE "logr_enable" -#define SMB_CD_MLRPC_KALIVE "mlrpc_keep_alive_interval" - -#define SMB_CD_MAX_BUFSIZE "max_bufsize" -#define SMB_CD_MAX_WORKERS "max_workers" -#define SMB_CD_MAX_CONNECTIONS "max_connections" -#define SMB_CD_KEEPALIVE "keep_alive" -#define SMB_CD_RESTRICT_ANON "restrict_anonymous" - -#define SMB_CD_SIGNING_ENABLE "signing_enabled" -#define SMB_CD_SIGNING_REQD "signing_required" -#define SMB_CD_SIGNING_CHECK "signing_check" - -#define SMB_CD_FLUSH_REQUIRED "flush_required" -#define SMB_CD_SYNC_ENABLE "sync_enable" -#define SMB_CD_DIRSYMLINK_DISABLE "dir_symlink_disable" -#define SMB_CD_ANNONCE_QUOTA "announce_quota" - -#define SMB_CD_SECURITY "security" -#define SMB_CD_NBSCOPE "netbios_scope" -#define SMB_CD_SYS_CMNT "system_comment" -#define SMB_CD_LM_LEVEL "lmauth_level" -#define SMB_CD_MSDCS_DISABLE "msdcs_disable" - -#define SMB_CD_ADS_ENABLE "ads_enable" -#define SMB_CD_ADS_USER "ads_user" -#define SMB_CD_ADS_PASSWD "ads_passwd" -#define SMB_CD_ADS_DOMAIN "ads_domain" -#define SMB_CD_ADS_USER_CONTAINER "ads_user_container" -#define SMB_CD_ADS_SITE "ads_site" -#define SMB_CD_ADS_IPLOOKUP "ads_ip_lookup" - -#define SMB_CD_DYNDNS_ENABLE "ddns_enable" -#define SMB_CD_DYNDNS_RETRY_COUNT "ddns_retry_cnt" -#define SMB_CD_DYNDNS_RETRY_SEC "ddns_retry_sec" - -#define SMB_CD_MACHINE_PASSWD "machine_passwd" - -/* configuration identifier */ typedef enum { - SMB_CI_RDR_IPCMODE = 0, - SMB_CI_RDR_IPCUSER, - SMB_CI_RDR_IPCPWD, - - SMB_CI_OPLOCK_ENABLE, + SMB_CI_OPLOCK_ENABLE = 0, SMB_CI_OPLOCK_TIMEOUT, SMB_CI_AUTOHOME_MAP, @@ -179,7 +118,6 @@ typedef enum { SMB_CI_WINS_EXCL, SMB_CI_SRVSVC_SHRSET_ENABLE, - SMB_CI_LOGR_ENABLE, SMB_CI_MLRPC_KALIVE, SMB_CI_MAX_BUFSIZE, @@ -201,19 +139,10 @@ typedef enum { SMB_CI_NBSCOPE, SMB_CI_SYS_CMNT, SMB_CI_LM_LEVEL, - SMB_CI_MSDCS_DISABLE, - SMB_CI_ADS_ENABLE, - SMB_CI_ADS_USER, - SMB_CI_ADS_PASSWD, - SMB_CI_ADS_DOMAIN, - SMB_CI_ADS_USER_CONTAINER, SMB_CI_ADS_SITE, - SMB_CI_ADS_IPLOOKUP, SMB_CI_DYNDNS_ENABLE, - SMB_CI_DYNDNS_RETRY_COUNT, - SMB_CI_DYNDNS_RETRY_SEC, SMB_CI_MACHINE_PASSWD, SMB_CI_MAX @@ -236,41 +165,20 @@ extern int smb_smf_set_opaque_property(smb_scfhandle_t *, char *, extern int smb_smf_get_opaque_property(smb_scfhandle_t *, char *, void *, size_t); extern int smb_smf_create_service_pgroup(smb_scfhandle_t *, char *); -extern int smb_smf_delete_service_pgroup(smb_scfhandle_t *, char *); -extern int smb_smf_create_instance_pgroup(smb_scfhandle_t *, char *); -extern int smb_smf_delete_instance_pgroup(smb_scfhandle_t *, char *); -extern int smb_smf_delete_property(smb_scfhandle_t *, char *); -extern int smb_smf_instance_exists(smb_scfhandle_t *, char *); -extern int smb_smf_instance_create(smb_scfhandle_t *, char *, char *); -extern int smb_smf_instance_delete(smb_scfhandle_t *, char *); -extern smb_scfhandle_t *smb_smf_get_iterator(char *); -extern int smb_smf_get_property(smb_scfhandle_t *, int, char *, char *, - size_t); -extern int smb_smf_set_property(smb_scfhandle_t *, int, char *, char *); /* Configuration management functions */ -extern int smb_config_load(void); -extern void smb_config_rdlock(void); -extern void smb_config_wrlock(void); -extern void smb_config_unlock(void); -extern char *smb_config_get(smb_cfg_id_t); -extern char *smb_config_getstr(smb_cfg_id_t); -extern int smb_config_getyorn(smb_cfg_id_t); -extern uint32_t smb_config_getnum(smb_cfg_id_t); - -/* - * smb_config_getenv - * - * Retrieves the property value from SMF. - * Caller must free the returned buffer. - * - */ -extern char *smb_config_getenv(smb_cfg_id_t id); +extern int smb_config_get(smb_cfg_id_t, char *, int); +extern char *smb_config_getname(smb_cfg_id_t); +extern int smb_config_getstr(smb_cfg_id_t, char *, int); +extern int smb_config_getnum(smb_cfg_id_t, int64_t *); +extern boolean_t smb_config_getbool(smb_cfg_id_t); extern int smb_config_set(smb_cfg_id_t, char *); -extern int smb_config_setnum(smb_cfg_id_t, uint32_t); +extern int smb_config_setstr(smb_cfg_id_t, char *); +extern int smb_config_setnum(smb_cfg_id_t, int64_t); +extern int smb_config_setbool(smb_cfg_id_t, boolean_t); + extern uint8_t smb_config_get_fg_flag(void); -extern int smb_config_setenv(smb_cfg_id_t id, char *); extern char *smb_config_get_localsid(void); extern int smb_config_secmode_fromstr(char *secmode); extern char *smb_config_secmode_tostr(int secmode); @@ -283,7 +191,7 @@ extern int smb_config_refresh(void); /* smb_door_client.c */ typedef struct smb_joininfo { - char domain_name[SMB_PI_MAX_DOMAIN]; + char domain_name[MAXHOSTNAMELEN]; char domain_username[BUF_LEN + 1]; char domain_passwd[BUF_LEN + 1]; uint32_t mode; @@ -293,10 +201,8 @@ typedef struct smb_joininfo { extern int smbd_set_param(smb_cfg_id_t, char *); extern int smbd_get_param(smb_cfg_id_t, char *); extern int smbd_get_security_mode(int *); -extern int smb_set_machine_pwd(char *); extern int smbd_netbios_reconfig(void); extern uint32_t smb_join(smb_joininfo_t *info); -extern int smb_ads_domain_change_notify(char *); #define SMB_DOMAIN_NOMACHINE_SID -1 @@ -317,22 +223,15 @@ extern int smb_wins_iplist(char *list, uint32_t iplist[], int max_naddr); * name of a controller (PDC or BDC) and it's ip address. */ typedef struct smb_ntdomain { - char domain[SMB_PI_MAX_DOMAIN_U]; - char server[SMB_PI_MAX_DOMAIN_U]; + char domain[SMB_PI_MAX_DOMAIN]; + char server[SMB_PI_MAX_DOMAIN]; uint32_t ipaddr; } smb_ntdomain_t; /* SMB domain information management functions */ -extern void smb_purge_domain_info(void); -extern int smb_is_domain_member(void); -extern uint8_t smb_get_fg_flag(void); -extern void smb_set_domain_member(int set); extern smb_ntdomain_t *smb_getdomaininfo(uint32_t timeout); extern void smb_setdomaininfo(char *domain, char *server, uint32_t ipaddr); extern void smb_logdomaininfo(smb_ntdomain_t *di); -extern uint32_t smb_get_security_mode(void); - -extern int nt_priv_presentable_num(void); /* * Following set of function, handle calls to SMB Kernel driver, via @@ -373,9 +272,12 @@ extern char *trim_whitespace(char *buf); extern void randomize(char *, unsigned); extern void rand_hash(unsigned char *, size_t, unsigned char *, size_t); +extern int smb_resolve_netbiosname(char *, char *, size_t); +extern int smb_resolve_fqdn(char *, char *, size_t); extern int smb_getdomainname(char *, size_t); -extern int smb_getfqhostname(char *, size_t); +extern int smb_getfqdomainname(char *, size_t); extern int smb_gethostname(char *, size_t, int); +extern int smb_getfqhostname(char *, size_t); extern int smb_getnetbiosname(char *, size_t); void smb_trace(const char *s); @@ -493,14 +395,6 @@ typedef struct smb_auth_info { smb_auth_data_blob_t data_blob; } smb_auth_info_t; -extern int smb_getdomainname(char *, size_t); -extern int smb_getfqhostname(char *, size_t); -extern int smb_gethostname(char *, size_t, int); -extern int smb_getnetbiosname(char *, size_t); - -void smb_trace(const char *s); -void smb_tracef(const char *fmt, ...); - /* * SMB password management */ @@ -567,9 +461,9 @@ extern int smb_auth_set_info(char *, char *, extern int smb_auth_gen_session_key(smb_auth_info_t *, unsigned char *); boolean_t smb_auth_validate_lm(unsigned char *, uint32_t, smb_passwd_t *, - unsigned char *, int, char *); + unsigned char *, int, char *, char *); boolean_t smb_auth_validate_nt(unsigned char *, uint32_t, smb_passwd_t *, - unsigned char *, int, char *); + unsigned char *, int, char *, char *); /* * SMB MAC Signing @@ -682,97 +576,94 @@ nt_domain_t *nt_domain_lookup_sid(nt_sid_t *domain_sid); nt_domain_t *nt_domain_lookupbytype(nt_domain_type_t type); nt_sid_t *nt_domain_local_sid(void); -#define SMB_GROUP_PER_LIST 5 - -/* - * This structure takes different args passed from the client/server routines - * of the SMB local group door service. Extend this structure if a new type - * client paramater needs to be passed. - */ -typedef struct ntgrp_dr_arg { - char *gname; - char *desc; - char *member; - char *newgname; - uint32_t privid; - uint32_t priv_attr; - int offset; - char *scope; - int type; - int count; - uint32_t ntstatus; -} ntgrp_dr_arg_t; - -typedef struct ntgrp { - DWORD rid; /* Rid of the group */ - char *name; /* Name of the group */ - char *desc; /* Desc of gruup */ - char *type; /* sid_name_use */ - char *sid; /* Sid */ - DWORD attr; /* Attribute */ -} ntgrp_t; - -typedef struct ntgrp_list { - int cnt; - ntgrp_t groups[SMB_GROUP_PER_LIST]; -} ntgrp_list_t; - -typedef char *members_list; -typedef struct ntgrp_member_list { - DWORD rid; /* Rid of the group in which members belong */ - int cnt; /* members */ - members_list members[SMB_GROUP_PER_LIST]; -} ntgrp_member_list_t; - -typedef struct ntpriv { - DWORD id; /* Id of priv */ - char *name; /* Name of priv */ -} ntpriv_t; -typedef ntpriv_t *privs_t; - -typedef struct ntpriv_list { - int cnt; /* Number of privs */ - privs_t privs[ANY_SIZE_ARRAY]; /* privs only presentable ones */ -} ntpriv_list_t; - - -/* the xdr functions */ -extern bool_t xdr_ntgrp_dr_arg_t(XDR *, ntgrp_dr_arg_t *); -extern bool_t xdr_ntgrp_t(XDR *, ntgrp_t *); -extern bool_t xdr_ntgrp_list_t(XDR *, ntgrp_list_t *); -extern bool_t xdr_members_list(XDR *, members_list *); -extern bool_t xdr_ntgrp_member_list_t(XDR *, ntgrp_member_list_t *); -extern bool_t xdr_ntpriv_t(XDR *, ntpriv_t *); -extern bool_t xdr_privs_t(XDR *, privs_t *); -extern bool_t xdr_ntpriv_list_t(XDR *, ntpriv_list_t *); - -extern void smb_group_free_memberlist(ntgrp_member_list_t *, int); -extern void smb_group_free_list(ntgrp_list_t *, int); -extern void smb_group_free_privlist(ntpriv_list_t *, int); - -extern uint32_t smb_group_add(char *, char *); -extern uint32_t smb_group_modify(char *, char *, char *); -extern uint32_t smb_group_delete(char *); -extern uint32_t smb_group_member_remove(char *, char *); -extern uint32_t smb_group_member_add(char *, char *); -extern uint32_t smb_group_priv_num(int *); -extern uint32_t smb_group_priv_list(ntpriv_list_t **); -extern uint32_t smb_group_priv_get(char *, uint32_t, uint32_t *); -extern uint32_t smb_group_priv_set(char *, uint32_t, uint32_t); -extern uint32_t smb_group_count(int *); -extern uint32_t smb_group_list(int, ntgrp_list_t **, char *, int); -extern uint32_t smb_group_member_count(char *, int *); -extern uint32_t smb_group_member_list(char *, int, ntgrp_member_list_t **); - -extern char *smb_dr_encode_grp_privlist(uint32_t, ntpriv_list_t *, size_t *); -extern ntpriv_list_t *smb_dr_decode_grp_privlist(char *, size_t); - -extern char *smb_dr_encode_grp_list(uint32_t, ntgrp_list_t *, size_t *); -extern ntgrp_list_t *smb_dr_decode_grp_list(char *, size_t); - -extern char *smb_dr_encode_grp_memberlist(uint32_t, ntgrp_member_list_t *, - size_t *); -extern ntgrp_member_list_t *smb_dr_decode_grp_memberlist(char *buf, size_t len); +typedef enum { + SMB_LGRP_BUILTIN = 1, + SMB_LGRP_LOCAL +} smb_gdomain_t; + +typedef struct smb_gsid { + nt_sid_t *gs_sid; + uint16_t gs_type; +} smb_gsid_t; + +typedef struct smb_giter { + sqlite_vm *sgi_vm; + sqlite *sgi_db; +} smb_giter_t; + +typedef struct smb_group { + char *sg_name; + char *sg_cmnt; + uint32_t sg_attr; + uint32_t sg_rid; + smb_gsid_t sg_id; + smb_gdomain_t sg_domain; + smb_privset_t *sg_privs; + uint32_t sg_nmembers; + smb_gsid_t *sg_members; +} smb_group_t; + +int smb_lgrp_start(void); +void smb_lgrp_stop(void); +int smb_lgrp_add(char *, char *); +int smb_lgrp_rename(char *, char *); +int smb_lgrp_delete(char *); +int smb_lgrp_setcmnt(char *, char *); +int smb_lgrp_getcmnt(char *, char **); +int smb_lgrp_getpriv(char *, uint8_t, boolean_t *); +int smb_lgrp_setpriv(char *, uint8_t, boolean_t); +int smb_lgrp_add_member(char *, nt_sid_t *, uint16_t); +int smb_lgrp_del_member(char *, nt_sid_t *, uint16_t); +int smb_lgrp_getbyname(char *, smb_group_t *); +int smb_lgrp_getbyrid(uint32_t, smb_gdomain_t, smb_group_t *); +int smb_lgrp_numbydomain(smb_gdomain_t, int *); +int smb_lgrp_numbymember(nt_sid_t *, int *); +void smb_lgrp_free(smb_group_t *); +boolean_t smb_lgrp_is_member(smb_group_t *, nt_sid_t *); +char *smb_lgrp_strerror(int); +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(nt_sid_t *, char *buf, int buflen); +int smb_lookup_name(char *, smb_gsid_t *); + +#define SMB_LGRP_SUCCESS 0 +#define SMB_LGRP_INVALID_ARG 1 +#define SMB_LGRP_INVALID_MEMBER 2 +#define SMB_LGRP_INVALID_NAME 3 +#define SMB_LGRP_NOT_FOUND 4 +#define SMB_LGRP_EXISTS 5 +#define SMB_LGRP_NO_SID 6 +#define SMB_LGRP_NO_LOCAL_SID 7 +#define SMB_LGRP_SID_NOTLOCAL 8 +#define SMB_LGRP_WKSID 9 +#define SMB_LGRP_NO_MEMORY 10 +#define SMB_LGRP_DB_ERROR 11 +#define SMB_LGRP_DBINIT_ERROR 12 +#define SMB_LGRP_INTERNAL_ERROR 13 +#define SMB_LGRP_MEMBER_IN_GROUP 14 +#define SMB_LGRP_MEMBER_NOT_IN_GROUP 15 +#define SMB_LGRP_NO_SUCH_PRIV 16 +#define SMB_LGRP_NO_SUCH_DOMAIN 17 +#define SMB_LGRP_PRIV_HELD 18 +#define SMB_LGRP_PRIV_NOT_HELD 19 +#define SMB_LGRP_BAD_DATA 20 +#define SMB_LGRP_NO_MORE 21 +#define SMB_LGRP_DBOPEN_FAILED 22 +#define SMB_LGRP_DBEXEC_FAILED 23 +#define SMB_LGRP_DBINIT_FAILED 24 +#define SMB_LGRP_DOMLKP_FAILED 25 +#define SMB_LGRP_DOMINS_FAILED 26 +#define SMB_LGRP_INSERT_FAILED 27 +#define SMB_LGRP_DELETE_FAILED 28 +#define SMB_LGRP_UPDATE_FAILED 29 +#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) #ifdef __cplusplus } diff --git a/usr/src/lib/smbsrv/libsmb/common/mapfile-vers b/usr/src/lib/smbsrv/libsmb/common/mapfile-vers index 3fa172f5d6..c5ad0f8219 100644 --- a/usr/src/lib/smbsrv/libsmb/common/mapfile-vers +++ b/usr/src/lib/smbsrv/libsmb/common/mapfile-vers @@ -18,7 +18,7 @@ # CDDL HEADER END # # -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -108,7 +108,6 @@ SUNWprivate { oemstounicodes; rand_hash; randomize; - smb_ads_domain_change_notify; smb_auth_DES; smb_auth_gen_session_key; smb_auth_ntlm_hash; @@ -120,12 +119,10 @@ SUNWprivate { smb_config_get_fg_flag; smb_config_get_localsid; smb_config_get_secmode; - smb_config_getenv; + smb_config_getbool; + smb_config_getname; smb_config_getnum; smb_config_getstr; - smb_config_getyorn; - smb_config_load; - smb_config_rdlock; smb_config_refresh; smb_config_refresh_idmap; smb_config_secmode_fromstr; @@ -133,26 +130,19 @@ SUNWprivate { smb_config_set; smb_config_set_idmap_domain; smb_config_set_secmode; - smb_config_setenv; + smb_config_setbool; smb_config_setnum; - smb_config_unlock; - smb_config_wrlock; + smb_config_setstr; smb_ctxbuf_init; smb_ctxbuf_len; smb_ctxbuf_printf; smb_dr_decode_arg_get_token; smb_dr_decode_common; smb_dr_decode_finish; - smb_dr_decode_grp_list; - smb_dr_decode_grp_memberlist; - smb_dr_decode_grp_privlist; smb_dr_decode_start; smb_dr_decode_string; smb_dr_encode_common; smb_dr_encode_finish; - smb_dr_encode_grp_list; - smb_dr_encode_grp_memberlist; - smb_dr_encode_grp_privlist; smb_dr_encode_res_token; smb_dr_encode_start; smb_dr_encode_string; @@ -193,41 +183,47 @@ SUNWprivate { smb_dwncall_install_callback; smb_dwncall_share; smb_dwncall_user_num; - smb_get_fg_flag; - smb_get_security_mode; smb_getdomaininfo; smb_getdomainname; + smb_getfqdomainname; smb_getfqhostname; smb_gethostname; smb_getnetbiosname; - smb_group_add; - smb_group_count; - smb_group_delete; - smb_group_free_list; - smb_group_free_memberlist; - smb_group_free_privlist; - smb_group_list; - smb_group_member_add; - smb_group_member_count; - smb_group_member_list; - smb_group_member_remove; - smb_group_modify; - smb_group_priv_get; - smb_group_priv_list; - smb_group_priv_num; - smb_group_priv_set; smb_idmap_batch_create; smb_idmap_batch_destroy; smb_idmap_batch_getid; smb_idmap_batch_getmappings; smb_idmap_batch_getsid; + smb_idmap_getid; smb_idmap_getsid; smb_idmap_restart; smb_idmap_start; smb_idmap_stop; - smb_is_domain_member; smb_join; + smb_lgrp_add; + smb_lgrp_add_member; + smb_lgrp_delete; + smb_lgrp_del_member; + smb_lgrp_free; + smb_lgrp_getbyname; + smb_lgrp_getbyrid; + smb_lgrp_getcmnt; + smb_lgrp_getpriv; + smb_lgrp_is_member; + smb_lgrp_iterate; + smb_lgrp_iterclose; + smb_lgrp_iteropen; + smb_lgrp_numbydomain; + smb_lgrp_numbymember; + smb_lgrp_rename; + smb_lgrp_setcmnt; + smb_lgrp_setpriv; + smb_lgrp_start; + smb_lgrp_stop; + smb_lgrp_strerror; smb_load_kconfig; + smb_lookup_name; + smb_lookup_sid; smb_mac_chk; smb_mac_dec_seqnum; smb_mac_inc_seqnum; @@ -245,37 +241,25 @@ SUNWprivate { smb_privset_free; smb_privset_init; smb_privset_log; + smb_privset_merge; smb_privset_new; smb_privset_query; smb_privset_size; smb_privset_validate; - smb_purge_domain_info; smb_trace; smb_tracef; - xdr_ntgrp_dr_arg_t; - xdr_ntgrp_list_t; - xdr_ntgrp_member_list_t; - xdr_ntpriv_list_t; smb_pwd_getpasswd; smb_pwd_setcntl; smb_pwd_setpasswd; - smb_set_domain_member; - smb_set_machine_pwd; + smb_resolve_fqdn; + smb_resolve_netbiosname; smb_setdomaininfo; - smb_smf_create_instance_pgroup; smb_smf_create_service_pgroup; - smb_smf_delete_instance_pgroup; - smb_smf_delete_property; - smb_smf_delete_service_pgroup; smb_smf_end_transaction; smb_smf_get_boolean_property; smb_smf_get_integer_property; - smb_smf_get_iterator; smb_smf_get_opaque_property; smb_smf_get_string_property; - smb_smf_instance_create; - smb_smf_instance_delete; - smb_smf_instance_exists; smb_smf_scf_fini; smb_smf_scf_init; smb_smf_set_boolean_property; @@ -313,10 +297,6 @@ SUNWprivate { utf8_strlwr; utf8_strncasecmp; utf8_strupr; - xdr_ntgrp_dr_arg_t; - xdr_ntgrp_list_t; - xdr_ntgrp_member_list_t; - xdr_ntpriv_list_t; xdr_smb_dr_bytes_t; xdr_smb_dr_string_t; xdr_smb_dr_ulist_t; 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 4a84b5d462..79a512be2d 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 @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -47,20 +47,8 @@ char *smbapi_desc[] = { "", "", "SmbapiUserList", - "SmbGroupAdd", - "SmbGroupDelete", - "SmbGroupAddMember", - "SmbGroupRemoveMember", - "SmbGroupGetCount", - "SmbGroupGetCacheSize", - "SmbGroupModify", - "SmbGroupPresentablePrivNum", - "SmbGroupPresentablePriv", - "SmbGroupGetPriv", - "SmbGroupSetPriv", - "SmbGroupListGroups", - "SmbGroupListMembers", - "SmbGroupMembersCount", + "SmbLookupSid", + "SmbLookupName", 0 }; @@ -104,535 +92,48 @@ smb_api_ulist(int offset, smb_dr_ulist_t *users) return (rc); } -/* Routines for SMB Group Door Client APIs */ -uint32_t -smb_group_add(char *gname, char *desc) -{ - ntgrp_dr_arg_t *args; - char *buf, *rbufp; - size_t buflen, rbufsize; - uint32_t rc = NT_STATUS_UNSUCCESSFUL; - int opcode = SMB_DR_GROUP_ADD; - int fd; - - if ((gname == 0) || (*gname == 0)) { - syslog(LOG_ERR, "%s: invalid parameter(s)", - smbapi_desc[opcode]); - return (NT_STATUS_INVALID_PARAMETER); - } - - if (smb_dr_clnt_open(&fd, SMB_DR_SVC_NAME, smbapi_desc[opcode]) == -1) - return (NT_STATUS_INTERNAL_ERROR); - - /* Encode */ - if ((args = (ntgrp_dr_arg_t *)malloc(sizeof (ntgrp_dr_arg_t))) == 0) { - syslog(LOG_ERR, "%s: cannot allocate memory", - smbapi_desc[opcode]); - (void) close(fd); - return (NT_STATUS_NO_MEMORY); - } - bzero(args, sizeof (ntgrp_dr_arg_t)); - args->gname = gname; - args->desc = desc; - if ((buf = smb_dr_encode_common(opcode, args, - xdr_ntgrp_dr_arg_t, &buflen)) == 0) { - syslog(LOG_ERR, "%s: Encode error", smbapi_desc[opcode]); - free(args); - (void) close(fd); - return (NT_STATUS_INTERNAL_ERROR); - } - free(args); - - rbufp = smb_dr_clnt_call(fd, buf, buflen, &rbufsize, - smbapi_desc[opcode]); - - /* Decode Result. */ - if (rbufp) { - if (smb_dr_decode_common(rbufp + SMB_DR_DATA_OFFSET, - rbufsize - SMB_DR_DATA_OFFSET, xdr_uint32_t, &rc) != 0) { - (void) close(fd); - return (NT_STATUS_INTERNAL_ERROR); - } - } - - smb_dr_clnt_free(buf, buflen, rbufp, rbufsize); - (void) close(fd); - return (rc); -} - -uint32_t -smb_group_delete(char *gname) -{ - char *buf, *rbufp; - size_t buflen, rbufsize; - uint32_t rc = NT_STATUS_UNSUCCESSFUL; - int opcode = SMB_DR_GROUP_DELETE; - int fd; - - if ((gname == 0) || (*gname == 0)) { - syslog(LOG_ERR, "%s: invalid parameter(s)", - smbapi_desc[opcode]); - return (NT_STATUS_INVALID_PARAMETER); - } - - if (smb_dr_clnt_open(&fd, SMB_DR_SVC_NAME, smbapi_desc[opcode]) == -1) - return (NT_STATUS_INTERNAL_ERROR); - - /* Encode */ - if ((buf = smb_dr_encode_string(opcode, gname, &buflen)) == 0) { - syslog(LOG_ERR, "%s: Encode error", smbapi_desc[opcode]); - (void) close(fd); - return (NT_STATUS_INTERNAL_ERROR); - } - - rbufp = smb_dr_clnt_call(fd, buf, buflen, &rbufsize, - smbapi_desc[opcode]); - - /* Decode Result. */ - if (rbufp) { - if (smb_dr_decode_common(rbufp + SMB_DR_DATA_OFFSET, - rbufsize - SMB_DR_DATA_OFFSET, xdr_uint32_t, &rc) != 0) { - (void) close(fd); - return (NT_STATUS_INTERNAL_ERROR); - } - } - - smb_dr_clnt_free(buf, buflen, rbufp, rbufsize); - (void) close(fd); - return (rc); -} - -uint32_t -smb_group_member_add(char *gname, char *member) -{ - ntgrp_dr_arg_t *args; - char *buf, *rbufp; - size_t buflen, rbufsize; - uint32_t rc = NT_STATUS_UNSUCCESSFUL; - int opcode = SMB_DR_GROUP_MEMBER_ADD; - int fd; - - if ((gname == 0) || (*gname == 0) || - (member == 0) || (*member == 0)) { - syslog(LOG_ERR, "%s: invalid parameter(s)", - smbapi_desc[opcode]); - return (NT_STATUS_INVALID_PARAMETER); - } - - if (smb_dr_clnt_open(&fd, SMB_DR_SVC_NAME, smbapi_desc[opcode]) == -1) - return (NT_STATUS_INTERNAL_ERROR); - - /* Encode */ - if ((args = (ntgrp_dr_arg_t *)malloc(sizeof (ntgrp_dr_arg_t))) == 0) { - syslog(LOG_ERR, "%s: cannot allocate memory", - smbapi_desc[opcode]); - (void) close(fd); - return (NT_STATUS_NO_MEMORY); - } - bzero(args, sizeof (ntgrp_dr_arg_t)); - args->gname = gname; - args->member = member; - if ((buf = smb_dr_encode_common(opcode, args, xdr_ntgrp_dr_arg_t, - &buflen)) == 0) { - syslog(LOG_ERR, "%s: Encode error", smbapi_desc[opcode]); - free(args); - (void) close(fd); - return (NT_STATUS_INTERNAL_ERROR); - } - free(args); - - rbufp = smb_dr_clnt_call(fd, buf, buflen, &rbufsize, - smbapi_desc[opcode]); - - /* Decode Result. */ - if (rbufp) { - if (smb_dr_decode_common(rbufp + SMB_DR_DATA_OFFSET, - rbufsize - SMB_DR_DATA_OFFSET, xdr_uint32_t, &rc) != 0) { - (void) close(fd); - return (NT_STATUS_INTERNAL_ERROR); - } - } - - smb_dr_clnt_free(buf, buflen, rbufp, rbufsize); - (void) close(fd); - return (rc); -} - -uint32_t -smb_group_member_remove(char *gname, char *member) -{ - ntgrp_dr_arg_t *args; - char *buf, *rbufp; - size_t buflen, rbufsize; - uint32_t rc = NT_STATUS_UNSUCCESSFUL; - int opcode = SMB_DR_GROUP_MEMBER_REMOVE; - int fd; - - if ((gname == 0) || (*gname == 0) || - (member == 0) || (*member == 0)) { - syslog(LOG_ERR, "%s: invalid parameter(s)", - smbapi_desc[opcode]); - return (NT_STATUS_INVALID_PARAMETER); - } - - if (smb_dr_clnt_open(&fd, SMB_DR_SVC_NAME, smbapi_desc[opcode]) == -1) - return (NT_STATUS_INTERNAL_ERROR); - - /* Encode */ - if ((args = (ntgrp_dr_arg_t *)malloc(sizeof (ntgrp_dr_arg_t))) == 0) { - syslog(LOG_ERR, "%s: cannot allocate memory", - smbapi_desc[opcode]); - (void) close(fd); - return (NT_STATUS_NO_MEMORY); - } - bzero(args, sizeof (ntgrp_dr_arg_t)); - args->gname = gname; - args->member = member; - if ((buf = smb_dr_encode_common(opcode, args, xdr_ntgrp_dr_arg_t, - &buflen)) == 0) { - syslog(LOG_ERR, "%s: Encode error", smbapi_desc[opcode]); - free(args); - (void) close(fd); - return (NT_STATUS_INTERNAL_ERROR); - } - free(args); - - rbufp = smb_dr_clnt_call(fd, buf, buflen, &rbufsize, - smbapi_desc[opcode]); - - /* Decode Result. */ - if (rbufp) { - if (smb_dr_decode_common(rbufp + SMB_DR_DATA_OFFSET, - rbufsize - SMB_DR_DATA_OFFSET, xdr_uint32_t, &rc) != 0) { - (void) close(fd); - return (NT_STATUS_INTERNAL_ERROR); - } - } - - smb_dr_clnt_free(buf, buflen, rbufp, rbufsize); - (void) close(fd); - return (rc); -} - - -uint32_t -smb_group_count(int *cnt) -{ - char *buf, *rbufp; - size_t buflen, rbufsize; - uint32_t rc = NT_STATUS_UNSUCCESSFUL; - uint_t opcode = SMB_DR_GROUP_COUNT; - int fd; - - if (cnt == 0) { - syslog(LOG_ERR, "%s: invalid parameter(s)", - smbapi_desc[opcode]); - return (NT_STATUS_INVALID_PARAMETER); - } - *cnt = 0; - if (smb_dr_clnt_open(&fd, SMB_DR_SVC_NAME, - smbapi_desc[opcode]) == -1) - return (NT_STATUS_INTERNAL_ERROR); - - if ((buf = smb_dr_set_opcode(opcode, &buflen)) == 0) { - (void) close(fd); - return (NT_STATUS_INVALID_PARAMETER); - } - - rbufp = smb_dr_clnt_call(fd, buf, buflen, &rbufsize, - smbapi_desc[opcode]); - - /* Decode Result */ - if (rbufp) { - if (smb_dr_decode_common(rbufp + SMB_DR_DATA_OFFSET, - rbufsize - SMB_DR_DATA_OFFSET, xdr_uint32_t, cnt) != 0) { - (void) close(fd); - return (NT_STATUS_INVALID_PARAMETER); - } - rc = NT_STATUS_SUCCESS; - } - - smb_dr_clnt_free(buf, buflen, rbufp, rbufsize); - (void) close(fd); - return (rc); -} - -uint32_t -smb_group_cachesize(int *sz) -{ - char *buf, *rbufp; - size_t buflen, rbufsize; - uint32_t rc = NT_STATUS_UNSUCCESSFUL; - uint_t opcode = SMB_DR_GROUP_CACHE_SIZE; - int fd; - - if (sz == 0) { - syslog(LOG_ERR, "%s: invalid parameter(s)", - smbapi_desc[opcode]); - return (NT_STATUS_INVALID_PARAMETER); - } - *sz = 0; - - if (smb_dr_clnt_open(&fd, SMB_DR_SVC_NAME, - smbapi_desc[opcode]) == -1) - return (NT_STATUS_INTERNAL_ERROR); - - if ((buf = smb_dr_set_opcode(opcode, &buflen)) == 0) { - (void) close(fd); - return (NT_STATUS_INVALID_PARAMETER); - } - - rbufp = smb_dr_clnt_call(fd, buf, buflen, &rbufsize, - smbapi_desc[opcode]); - - /* Decode Result */ - if (rbufp) { - if (smb_dr_decode_common(rbufp + SMB_DR_DATA_OFFSET, - rbufsize - SMB_DR_DATA_OFFSET, xdr_uint32_t, sz) != 0) { - (void) close(fd); - return (NT_STATUS_INVALID_PARAMETER); - } - rc = NT_STATUS_SUCCESS; - } - - smb_dr_clnt_free(buf, buflen, rbufp, rbufsize); - (void) close(fd); - return (rc); -} - -uint32_t -smb_group_modify(char *gname, char *newgname, char *desc) -{ - ntgrp_dr_arg_t *args; - char *buf, *rbufp; - size_t buflen, rbufsize; - uint32_t rc = NT_STATUS_UNSUCCESSFUL; - int opcode = SMB_DR_GROUP_MODIFY; - int fd; - - if ((gname == 0) || (*gname == 0) || - (newgname == 0) || (*newgname == 0)) { - syslog(LOG_ERR, "%s: invalid parameter(s)", - smbapi_desc[opcode]); - return (NT_STATUS_INVALID_PARAMETER); - } - - if (smb_dr_clnt_open(&fd, SMB_DR_SVC_NAME, smbapi_desc[opcode]) == -1) - return (NT_STATUS_INTERNAL_ERROR); - - /* Encode */ - if ((args = (ntgrp_dr_arg_t *)malloc(sizeof (ntgrp_dr_arg_t))) == 0) { - syslog(LOG_ERR, "%s: cannot allocate memory", - smbapi_desc[opcode]); - (void) close(fd); - return (NT_STATUS_NO_MEMORY); - } - bzero(args, sizeof (ntgrp_dr_arg_t)); - args->gname = gname; - args->desc = desc; - args->newgname = newgname; - if ((buf = smb_dr_encode_common(opcode, args, xdr_ntgrp_dr_arg_t, - &buflen)) == 0) { - syslog(LOG_ERR, "%s: Encode error", smbapi_desc[opcode]); - free(args); - (void) close(fd); - return (NT_STATUS_INTERNAL_ERROR); - } - free(args); - - rbufp = smb_dr_clnt_call(fd, buf, buflen, &rbufsize, - smbapi_desc[opcode]); - - /* Decode Result. */ - if (rbufp) { - if (smb_dr_decode_common(rbufp + SMB_DR_DATA_OFFSET, - rbufsize - SMB_DR_DATA_OFFSET, xdr_uint32_t, &rc) != 0) { - (void) close(fd); - return (NT_STATUS_INTERNAL_ERROR); - } - } - - smb_dr_clnt_free(buf, buflen, rbufp, rbufsize); - (void) close(fd); - return (rc); -} - -uint32_t -smb_group_priv_num(int *num) +int +smb_lookup_sid(nt_sid_t *sid, char *sidbuf, int sidbuflen) { char *buf, *rbufp; size_t buflen, rbufsize; - uint32_t rc = NT_STATUS_UNSUCCESSFUL; - int opcode = SMB_DR_GROUP_PRIV_NUM; + int opcode = SMB_DR_LOOKUP_SID; + char strsid[NT_SID_FMTBUF_SIZE]; + char *name = NULL; int fd; - if (num == 0) { + if ((sidbuf == NULL) || (sidbuflen == 0)) { syslog(LOG_ERR, "%s: invalid parameter(s)", smbapi_desc[opcode]); return (NT_STATUS_INVALID_PARAMETER); } - *num = 0; - - if (smb_dr_clnt_open(&fd, SMB_DR_SVC_NAME, - smbapi_desc[opcode]) == -1) - return (NT_STATUS_INTERNAL_ERROR); - - if ((buf = smb_dr_set_opcode(opcode, &buflen)) == 0) { - (void) close(fd); - return (NT_STATUS_INVALID_PARAMETER); - } - rbufp = smb_dr_clnt_call(fd, buf, buflen, &rbufsize, - smbapi_desc[opcode]); - - /* Decode Result */ - if (rbufp) { - if (smb_dr_decode_common(rbufp + SMB_DR_DATA_OFFSET, - rbufsize - SMB_DR_DATA_OFFSET, xdr_uint32_t, num) != 0) { - (void) close(fd); - return (NT_STATUS_INTERNAL_ERROR); - } - rc = NT_STATUS_SUCCESS; - } - - smb_dr_clnt_free(buf, buflen, rbufp, rbufsize); - (void) close(fd); - return (rc); -} - -uint32_t -smb_group_priv_list(ntpriv_list_t **list) -{ - char *buf, *rbufp; - size_t buflen, rbufsize; - uint32_t rc = NT_STATUS_UNSUCCESSFUL; - int opcode = SMB_DR_GROUP_PRIV_LIST; - int fd; - *list = NULL; - - if (smb_dr_clnt_open(&fd, SMB_DR_SVC_NAME, - smbapi_desc[opcode]) == -1) - return (NT_STATUS_INTERNAL_ERROR); - - if ((buf = smb_dr_set_opcode(opcode, &buflen)) == 0) { - (void) close(fd); - return (NT_STATUS_INVALID_PARAMETER); - } - - rbufp = smb_dr_clnt_call(fd, buf, buflen, &rbufsize, - smbapi_desc[opcode]); - - /* Decode Result */ - if (rbufp) { - if ((*list = smb_dr_decode_grp_privlist( - rbufp + SMB_DR_DATA_OFFSET, - rbufsize - SMB_DR_DATA_OFFSET)) == 0) { - (void) close(fd); - return (NT_STATUS_INTERNAL_ERROR); - } - rc = NT_STATUS_SUCCESS; - } - - smb_dr_clnt_free(buf, buflen, rbufp, rbufsize); - (void) close(fd); - return (rc); -} - -uint32_t -smb_group_priv_get(char *gname, uint32_t privid, uint32_t *privval) -{ - char *buf, *rbufp; - size_t buflen, rbufsize; - ntgrp_dr_arg_t *args; - uint32_t rc = NT_STATUS_UNSUCCESSFUL; - int opcode = SMB_DR_GROUP_PRIV_GET; - int fd; - uint32_t retval; - - *privval = SE_PRIVILEGE_DISABLED; - - if (smb_dr_clnt_open(&fd, SMB_DR_SVC_NAME, smbapi_desc[opcode]) == -1) - return (NT_STATUS_INTERNAL_ERROR); - - /* Encode */ - if ((args = (ntgrp_dr_arg_t *)malloc(sizeof (ntgrp_dr_arg_t))) == 0) { - syslog(LOG_ERR, "%s: cannot allocate memory", + if (!nt_sid_is_valid(sid)) { + syslog(LOG_ERR, "%s: invalid SID", smbapi_desc[opcode]); - (void) close(fd); - return (NT_STATUS_NO_MEMORY); + return (NT_STATUS_INVALID_SID); } - bzero(args, sizeof (ntgrp_dr_arg_t)); - args->gname = gname; - args->privid = privid; - if ((buf = smb_dr_encode_common(opcode, args, xdr_ntgrp_dr_arg_t, - &buflen)) == 0) { - syslog(LOG_ERR, "%s: Encode error", smbapi_desc[opcode]); - free(args); - (void) close(fd); - return (NT_STATUS_INTERNAL_ERROR); - } - free(args); - - rbufp = smb_dr_clnt_call(fd, buf, buflen, &rbufsize, - smbapi_desc[opcode]); - - /* Decode Result. */ - if (rbufp) { - if (smb_dr_decode_common(rbufp + SMB_DR_DATA_OFFSET, - rbufsize - SMB_DR_DATA_OFFSET, xdr_uint32_t, - &retval) != 0) { - (void) close(fd); - return (NT_STATUS_INTERNAL_ERROR); - } - *privval = retval; - rc = NT_STATUS_SUCCESS; - } - - smb_dr_clnt_free(buf, buflen, rbufp, rbufsize); - (void) close(fd); - return (rc); -} - -uint32_t -smb_group_priv_set(char *gname, uint32_t privid, uint32_t priv_attr) -{ - char *buf, *rbufp; - size_t buflen, rbufsize; - ntgrp_dr_arg_t *args; - uint32_t rc = NT_STATUS_UNSUCCESSFUL; - int opcode = SMB_DR_GROUP_PRIV_SET; - int fd; if (smb_dr_clnt_open(&fd, SMB_DR_SVC_NAME, smbapi_desc[opcode]) == -1) return (NT_STATUS_INTERNAL_ERROR); /* Encode */ - if ((args = (ntgrp_dr_arg_t *)malloc(sizeof (ntgrp_dr_arg_t))) == 0) { - syslog(LOG_ERR, "%s: cannot allocate memory", - smbapi_desc[opcode]); - (void) close(fd); - return (NT_STATUS_NO_MEMORY); - } - bzero(args, sizeof (ntgrp_dr_arg_t)); - args->gname = gname; - args->privid = privid; - args->priv_attr = priv_attr; - if ((buf = smb_dr_encode_common(opcode, args, xdr_ntgrp_dr_arg_t, - &buflen)) == 0) { + nt_sid_format2(sid, strsid); + if ((buf = smb_dr_encode_string(opcode, strsid, &buflen)) == 0) { syslog(LOG_ERR, "%s: Encode error", smbapi_desc[opcode]); - free(args); (void) close(fd); return (NT_STATUS_INTERNAL_ERROR); } - free(args); rbufp = smb_dr_clnt_call(fd, buf, buflen, &rbufsize, smbapi_desc[opcode]); /* Decode Result. */ if (rbufp) { - if (smb_dr_decode_common(rbufp + SMB_DR_DATA_OFFSET, - rbufsize - SMB_DR_DATA_OFFSET, xdr_uint32_t, &rc) != 0) { + name = smb_dr_decode_string(rbufp + SMB_DR_DATA_OFFSET, + rbufsize - SMB_DR_DATA_OFFSET); + if (name == NULL) { + smb_dr_clnt_free(buf, buflen, rbufp, rbufsize); (void) close(fd); return (NT_STATUS_INTERNAL_ERROR); } @@ -640,73 +141,26 @@ smb_group_priv_set(char *gname, uint32_t privid, uint32_t priv_attr) smb_dr_clnt_free(buf, buflen, rbufp, rbufsize); (void) close(fd); - return (rc); -} -uint32_t -smb_group_list(int offset, ntgrp_list_t **list, char *scope, int type) -{ - char *buf, *rbufp; - size_t buflen, rbufsize; - ntgrp_dr_arg_t *args; - uint32_t rc = NT_STATUS_UNSUCCESSFUL; - int opcode = SMB_DR_GROUP_LIST; - int fd; - *list = NULL; - - if (smb_dr_clnt_open(&fd, SMB_DR_SVC_NAME, smbapi_desc[opcode]) == -1) - return (NT_STATUS_INTERNAL_ERROR); + if ((name == NULL) || (*name == '\0')) + nt_sid_format2(sid, sidbuf); - /* Encode */ - if ((args = (ntgrp_dr_arg_t *)malloc(sizeof (ntgrp_dr_arg_t))) == 0) { - syslog(LOG_ERR, "%s: cannot allocate memory", - smbapi_desc[opcode]); - (void) close(fd); - return (NT_STATUS_NO_MEMORY); - } - bzero(args, sizeof (ntgrp_dr_arg_t)); - args->offset = offset; - args->type = type; - args->scope = scope; - if ((buf = smb_dr_encode_common(opcode, args, xdr_ntgrp_dr_arg_t, - &buflen)) == 0) { - syslog(LOG_ERR, "%s: Encode error", smbapi_desc[opcode]); - free(args); - (void) close(fd); - return (NT_STATUS_INTERNAL_ERROR); - } - free(args); - - rbufp = smb_dr_clnt_call(fd, buf, buflen, &rbufsize, - smbapi_desc[opcode]); - - /* Decode Result. */ - if (rbufp) { - if ((*list = smb_dr_decode_grp_list(rbufp + SMB_DR_DATA_OFFSET, - rbufsize - SMB_DR_DATA_OFFSET)) == 0) { - (void) close(fd); - return (NT_STATUS_INTERNAL_ERROR); - } - rc = NT_STATUS_SUCCESS; - } - - smb_dr_clnt_free(buf, buflen, rbufp, rbufsize); - (void) close(fd); - return (rc); + (void) strlcpy(sidbuf, name, sidbuflen); + xdr_free(xdr_string, (char *)&name); + return (NT_STATUS_SUCCESS); } -uint32_t -smb_group_member_list(char *gname, int offset, ntgrp_member_list_t **members) +int +smb_lookup_name(char *name, smb_gsid_t *sid) { char *buf, *rbufp; size_t buflen, rbufsize; - ntgrp_dr_arg_t *args; - uint32_t rc = NT_STATUS_UNSUCCESSFUL; - int opcode = SMB_DR_GROUP_MEMBER_LIST; + int opcode = SMB_DR_LOOKUP_NAME; + char *strsid = NULL; + char *p; int fd; - *members = NULL; - if ((gname == 0) || (*gname == 0)) { + if ((name == NULL) || (*name == '\0')) { syslog(LOG_ERR, "%s: invalid parameter(s)", smbapi_desc[opcode]); return (NT_STATUS_INVALID_PARAMETER); @@ -716,149 +170,38 @@ smb_group_member_list(char *gname, int offset, ntgrp_member_list_t **members) return (NT_STATUS_INTERNAL_ERROR); /* Encode */ - if ((args = (ntgrp_dr_arg_t *)malloc(sizeof (ntgrp_dr_arg_t))) == 0) { - syslog(LOG_ERR, "%s: cannot allocate memory for ret_mem_list", - smbapi_desc[opcode]); - (void) close(fd); - return (NT_STATUS_NO_MEMORY); - } - bzero(args, sizeof (ntgrp_dr_arg_t)); - args->gname = gname; - args->offset = offset; - if ((buf = smb_dr_encode_common(opcode, args, xdr_ntgrp_dr_arg_t, - &buflen)) == 0) { + if ((buf = smb_dr_encode_string(opcode, name, &buflen)) == 0) { syslog(LOG_ERR, "%s: Encode error", smbapi_desc[opcode]); - free(args); (void) close(fd); return (NT_STATUS_INTERNAL_ERROR); } - free(args); rbufp = smb_dr_clnt_call(fd, buf, buflen, &rbufsize, smbapi_desc[opcode]); /* Decode Result. */ if (rbufp) { - if ((*members = smb_dr_decode_grp_memberlist( - rbufp + SMB_DR_DATA_OFFSET, - rbufsize - SMB_DR_DATA_OFFSET)) == 0) { + strsid = smb_dr_decode_string(rbufp + SMB_DR_DATA_OFFSET, + rbufsize - SMB_DR_DATA_OFFSET); + if (strsid == NULL) { + smb_dr_clnt_free(buf, buflen, rbufp, rbufsize); (void) close(fd); return (NT_STATUS_INTERNAL_ERROR); } - rc = NT_STATUS_SUCCESS; - } - - smb_dr_clnt_free(buf, buflen, rbufp, rbufsize); - (void) close(fd); - return (rc); -} - -uint32_t -smb_group_member_count(char *gname, int *cnt) -{ - char *buf, *rbufp; - size_t buflen, rbufsize; - ntgrp_dr_arg_t *dec_args; - uint32_t rc = NT_STATUS_UNSUCCESSFUL; - int opcode = SMB_DR_GROUP_MEMBER_COUNT; - int fd; - - if ((gname == 0) || (*gname == 0) || (cnt == 0)) { - syslog(LOG_ERR, "%s: invalid parameter(s)", - smbapi_desc[opcode]); - return (NT_STATUS_INVALID_PARAMETER); } - if (smb_dr_clnt_open(&fd, SMB_DR_SVC_NAME, smbapi_desc[opcode]) == -1) - return (NT_STATUS_INTERNAL_ERROR); - - /* Encode */ - if ((buf = smb_dr_encode_string(opcode, gname, &buflen)) == 0) { - syslog(LOG_ERR, "%s: Encode error", smbapi_desc[opcode]); - (void) close(fd); - return (NT_STATUS_INTERNAL_ERROR); - } - - rbufp = smb_dr_clnt_call(fd, buf, buflen, &rbufsize, - smbapi_desc[opcode]); - - /* Decode Result. */ - if ((dec_args = (ntgrp_dr_arg_t *) - malloc(sizeof (ntgrp_dr_arg_t))) == 0) { - syslog(LOG_ERR, "%s: cannot allocate memory", - smbapi_desc[opcode]); - (void) close(fd); - return (NT_STATUS_NO_MEMORY); - } - bzero(dec_args, sizeof (ntgrp_dr_arg_t)); - if (rbufp) { - if (smb_dr_decode_common(rbufp + SMB_DR_DATA_OFFSET, - rbufsize - SMB_DR_DATA_OFFSET, xdr_ntgrp_dr_arg_t, dec_args) - != 0) { - free(dec_args); - (void) close(fd); - return (dec_args->ntstatus); - } - } - *cnt = dec_args->count; - rc = dec_args->ntstatus; smb_dr_clnt_free(buf, buflen, rbufp, rbufsize); - free(dec_args); (void) close(fd); - return (rc); -} -/* Helper functions for local group door service to free up data structures */ -void -smb_group_free_privlist(ntpriv_list_t *list, int deletelist) -{ - int i; - if (!list) - return; - if (list->privs != NULL) { - for (i = 0; i < list->cnt; i++) { - if (list->privs[i] != NULL) { - free(list->privs[i]->name); - free(list->privs[i]); - } - } - if (deletelist) - free(list); + p = strchr(strsid, '-'); + if (p == NULL) { + xdr_free(xdr_string, (char *)&strsid); + return (NT_STATUS_NONE_MAPPED); } -} -void -smb_group_free_list(ntgrp_list_t *list, int entries_only) -{ - int i; - - if (!list) { - return; - } - - for (i = 0; i < list->cnt; i++) { - free(list->groups[i].name); - free(list->groups[i].desc); - free(list->groups[i].type); - free(list->groups[i].sid); - } - if (!entries_only) - free(list); -} - -void -smb_group_free_memberlist(ntgrp_member_list_t *members, - int entries_only) -{ - int i; - - if (!members) { - return; - } - - for (i = 0; i < members->cnt; i++) { - free(members->members[i]); - } - if (!entries_only) - free(members); + *p++ = '\0'; + sid->gs_type = atoi(strsid); + sid->gs_sid = nt_sid_strtosid(p); + xdr_free(xdr_string, (char *)&strsid); + return (NT_STATUS_SUCCESS); } diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_auth.c b/usr/src/lib/smbsrv/libsmb/common/smb_auth.c index d8950616db..ccd33ca1af 100644 --- a/usr/src/lib/smbsrv/libsmb/common/smb_auth.c +++ b/usr/src/lib/smbsrv/libsmb/common/smb_auth.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -303,7 +303,6 @@ smb_auth_ntlmv2_hash(unsigned char *ntlm_hash, return (SMBAUTH_FAILURE); (void) utf8_strupr(username); - (void) utf8_strupr(ntdomain); data_len = strlen(username) + strlen(ntdomain); buf = (unsigned char *)malloc((data_len + 1) * sizeof (char)); @@ -397,6 +396,7 @@ smb_auth_set_info(char *username, unsigned short blob_len; unsigned char blob_buf[SMBAUTH_BLOB_MAXLEN]; int rc; + char *uppercase_dom; auth->lmcompatibility_lvl = lmcomp_lvl; if (lmcomp_lvl == 2) { @@ -421,12 +421,23 @@ smb_auth_set_info(char *username, (void) memcpy(auth->hash, ntlm_hash, SMBAUTH_HASH_SZ); } + if (!domain) + return (-1); + + if ((uppercase_dom = strdup(domain)) == NULL) + return (-1); + + (void) utf8_strupr(uppercase_dom); + if (smb_auth_ntlmv2_hash(auth->hash, username, - domain, auth->hash_v2) != SMBAUTH_SUCCESS) + uppercase_dom, auth->hash_v2) != SMBAUTH_SUCCESS) { + free(uppercase_dom); return (-1); + } /* generate data blob */ - smb_auth_gen_data_blob(&auth->data_blob, domain); + smb_auth_gen_data_blob(&auth->data_blob, uppercase_dom); + free(uppercase_dom); blob_len = smb_auth_blob_to_string(&auth->data_blob, blob_buf); /* generate NTLMv2 response */ @@ -538,67 +549,90 @@ smb_ntlmv2_password_ok( unsigned char *ntlm_hash, unsigned char *passwd, int pwdlen, + char *domain, char *username) { unsigned char *clnt_blob; int clnt_blob_len; unsigned char ntlmv2_hash[SMBAUTH_HASH_SZ]; unsigned char *ntlmv2_resp; - boolean_t ok; + boolean_t ok = B_FALSE; + char *dest[3]; + int i; clnt_blob_len = pwdlen - SMBAUTH_HASH_SZ; clnt_blob = &passwd[SMBAUTH_HASH_SZ]; + dest[0] = domain; + if ((dest[1] = strdup(domain)) == NULL) + return (B_FALSE); + (void) utf8_strupr(dest[1]); + dest[2] = ""; /* * 15.5.2 The NTLMv2 Password Hash, pg. 279, of the "Implementing CIFS" * - * * The NTLMv2 Hash is created from: + * The NTLMv2 Hash is created from: * - NTLM hash * - user's username, and * - the name of the logon destination(i.e. the NetBIOS name of either - * the SMB server or NT Domain against which the suer is trying to + * the SMB server or NT Domain against which the user is trying to * authenticate. * - * (N.L.) With my experience, this is not exactly true. It's really - * tricky how the NTLMv2 hash is generated by the Windows client when - * logging into a standalone server using NTLMv2 challenge / response. - * The NTLMv2 hash is actually created with the destination info="" - * as opposed to the SMB server name mentioned in the book. + * Experiments show this is not exactly the case. + * For Windows Server 2003, the domain name needs to be included and + * converted to uppercase. For Vista, the domain name needs to be + * included also, but leave the case alone. And in some cases it needs + * to be empty. All three variants are tried here. */ - if (smb_auth_ntlmv2_hash(ntlm_hash, username, "", ntlmv2_hash) != - SMBAUTH_SUCCESS) { - return (B_FALSE); - } ntlmv2_resp = (unsigned char *)malloc(SMBAUTH_HASH_SZ + clnt_blob_len); - if (ntlmv2_resp == NULL) - return (B_FALSE); - - if (smb_auth_v2_response(ntlmv2_hash, challenge, - clen, clnt_blob, clnt_blob_len, ntlmv2_resp) < 0) { - free(ntlmv2_resp); + if (ntlmv2_resp == NULL) { + free(dest[1]); return (B_FALSE); } - ok = (bcmp(passwd, ntlmv2_resp, pwdlen) == 0); + for (i = 0; i < (sizeof (dest) / sizeof (char *)); i++) { + if (smb_auth_ntlmv2_hash(ntlm_hash, username, dest[i], + ntlmv2_hash) != SMBAUTH_SUCCESS) + break; + + if (smb_auth_v2_response(ntlmv2_hash, challenge, + clen, clnt_blob, clnt_blob_len, ntlmv2_resp) < 0) + break; + + ok = (bcmp(passwd, ntlmv2_resp, pwdlen) == 0); + if (ok == B_TRUE) + break; + } + + free(dest[1]); free(ntlmv2_resp); return (ok); } -static int +static boolean_t smb_lmv2_password_ok( unsigned char *challenge, uint32_t clen, unsigned char *ntlm_hash, unsigned char *passwd, + char *domain, char *username) { unsigned char *clnt_challenge; unsigned char ntlmv2_hash[SMBAUTH_HASH_SZ]; unsigned char lmv2_resp[SMBAUTH_LM_RESP_SZ]; + boolean_t ok = B_FALSE; + char *dest[3]; + int i; clnt_challenge = &passwd[SMBAUTH_HASH_SZ]; + dest[0] = domain; + if ((dest[1] = strdup(domain)) == NULL) + return (B_FALSE); + (void) utf8_strupr(dest[1]); + dest[2] = ""; /* * 15.5.2 The NTLMv2 Password Hash, pg. 279, of the "Implementing CIFS" @@ -610,23 +644,31 @@ smb_lmv2_password_ok( * the SMB server or NT Domain against which the suer is trying to * authenticate. * - * (N.L.) With my experience, this is not exactly true. It's really - * tricky how the NTLMv2 hash is generated by the Windows client when - * logging into a standalone server using LMv2 challenge/response. - * The NTLMv2 hash is actually created with the destination info = "" - * as opposed to the SMB server name mentioned in the book. + * Experiments show this is not exactly the case. + * For Windows Server 2003, the domain name needs to be included and + * converted to uppercase. For Vista, the domain name needs to be + * included also, but leave the case alone. And in some cases it needs + * to be empty. All three variants are tried here. */ - if (smb_auth_ntlmv2_hash(ntlm_hash, username, "", ntlmv2_hash) != - SMBAUTH_SUCCESS) { - return (B_FALSE); - } - if (smb_auth_v2_response(ntlmv2_hash, challenge, - clen, clnt_challenge, SMBAUTH_V2_CLNT_CHALLENGE_SZ, - lmv2_resp) < 0) { - return (B_FALSE); + + for (i = 0; i < (sizeof (dest) / sizeof (char *)); i++) { + if (smb_auth_ntlmv2_hash(ntlm_hash, username, dest[i], + ntlmv2_hash) != SMBAUTH_SUCCESS) + break; + + if (smb_auth_v2_response(ntlmv2_hash, challenge, + clen, clnt_challenge, SMBAUTH_V2_CLNT_CHALLENGE_SZ, + lmv2_resp) < 0) + break; + + ok = (bcmp(passwd, lmv2_resp, SMBAUTH_LM_RESP_SZ) == 0); + if (ok == B_TRUE) + break; + } - return (bcmp(passwd, lmv2_resp, SMBAUTH_LM_RESP_SZ) == 0); + free(dest[1]); + return (ok); } /* @@ -644,17 +686,17 @@ smb_auth_validate_lm( smb_passwd_t *smbpw, unsigned char *passwd, int pwdlen, + char *domain, char *username) { - int lmlevel; boolean_t ok = B_FALSE; + int64_t lmlevel; if (pwdlen != SMBAUTH_LM_RESP_SZ) return (B_FALSE); - smb_config_rdlock(); - lmlevel = smb_config_getnum(SMB_CI_LM_LEVEL); - smb_config_unlock(); + if (smb_config_getnum(SMB_CI_LM_LEVEL, &lmlevel) != SMBD_SMF_OK) + return (B_FALSE); if (lmlevel <= 3) { ok = smb_lm_password_ok(challenge, clen, smbpw->pw_lmhash, @@ -663,7 +705,7 @@ smb_auth_validate_lm( if (!ok) ok = smb_lmv2_password_ok(challenge, clen, smbpw->pw_nthash, - passwd, username); + passwd, domain, username); return (ok); } @@ -683,21 +725,21 @@ smb_auth_validate_nt( smb_passwd_t *smbpw, unsigned char *passwd, int pwdlen, + char *domain, char *username) { - int lmlevel; + int64_t lmlevel; boolean_t ok; - smb_config_rdlock(); - lmlevel = smb_config_getnum(SMB_CI_LM_LEVEL); - smb_config_unlock(); + if (smb_config_getnum(SMB_CI_LM_LEVEL, &lmlevel) != SMBD_SMF_OK) + return (B_FALSE); if ((lmlevel == 5) && (pwdlen <= SMBAUTH_LM_RESP_SZ)) return (B_FALSE); if (pwdlen > SMBAUTH_LM_RESP_SZ) ok = smb_ntlmv2_password_ok(challenge, clen, - smbpw->pw_nthash, passwd, pwdlen, username); + smbpw->pw_nthash, passwd, pwdlen, domain, username); else ok = smb_ntlm_password_ok(challenge, clen, smbpw->pw_nthash, passwd); diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_cfg.c b/usr/src/lib/smbsrv/libsmb/common/smb_cfg.c index 84d95609e5..f5e6bb8a48 100644 --- a/usr/src/lib/smbsrv/libsmb/common/smb_cfg.c +++ b/usr/src/lib/smbsrv/libsmb/common/smb_cfg.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -40,27 +40,20 @@ #include <ctype.h> #include <sys/types.h> #include <libscf.h> +#include <assert.h> #include <smbsrv/libsmb.h> typedef struct smb_cfg_param { - char *sc_pg; + smb_cfg_id_t sc_id; char *sc_name; int sc_type; - char *sc_value; uint32_t sc_flags; } smb_cfg_param_t; /* * config parameter flags */ -#define SMB_CF_NOTINIT 0x00 /* Not initialized yet */ -#define SMB_CF_DEFINED 0x01 /* Defined/read from env */ -#define SMB_CF_MODIFIED 0x02 /* Has been modified */ -#define SMB_CF_SYSTEM 0x04 /* system; not part of cifs config */ - -#define SMB_CL_NONE 0 -#define SMB_CL_READ 1 -#define SMB_CL_WRITE 2 +#define SMB_CF_PROTECTED 0x01 /* idmap SMF fmri and Property Group */ #define IDMAP_FMRI_PREFIX "system/idmap" @@ -77,115 +70,79 @@ typedef struct smb_cfg_param { static char *b64_data = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; -static rwlock_t smb_cfg_rwlk; -static int lock_type = SMB_CL_NONE; - -/* - * IMPORTANT: any changes to the order of this table's entries - * need to be reflected in smb_cfg_id_t enum in libsmb.h - */ static smb_cfg_param_t smb_cfg_table[] = { - /* Redirector configuration, User space */ - {SMBD_PG_NAME, SMB_CD_RDR_IPCMODE, SCF_TYPE_ASTRING, 0, SMB_CF_NOTINIT}, - {SMBD_PROTECTED_PG_NAME, SMB_CD_RDR_IPCUSER, - SCF_TYPE_ASTRING, 0, SMB_CF_NOTINIT}, - {SMBD_PROTECTED_PG_NAME, SMB_CD_RDR_IPCPWD, - SCF_TYPE_ASTRING, 0, SMB_CF_NOTINIT}, - /* Oplock configuration, Kernel Only */ - {SMBD_PG_NAME, SMB_CD_OPLOCK_ENABLE, - SCF_TYPE_BOOLEAN, 0, SMB_CF_NOTINIT}, - {SMBD_PG_NAME, SMB_CD_OPLOCK_TIMEOUT, - SCF_TYPE_INTEGER, 0, SMB_CF_NOTINIT}, + {SMB_CI_OPLOCK_ENABLE, "oplock_enable", SCF_TYPE_BOOLEAN, 0}, + {SMB_CI_OPLOCK_TIMEOUT, "oplock_timeout", SCF_TYPE_INTEGER, 0}, /* Autohome configuration */ - {SMBD_PG_NAME, SMB_CD_AUTOHOME_MAP, - SCF_TYPE_ASTRING, 0, SMB_CF_NOTINIT}, + {SMB_CI_AUTOHOME_MAP, "autohome_map", SCF_TYPE_ASTRING, 0}, /* Domain/PDC configuration */ - {SMBD_PG_NAME, SMB_CD_DOMAIN_SID, SCF_TYPE_ASTRING, 0, SMB_CF_NOTINIT}, - {SMBD_PG_NAME, SMB_CD_DOMAIN_MEMB, SCF_TYPE_BOOLEAN, 0, SMB_CF_NOTINIT}, - {SMBD_PG_NAME, SMB_CD_DOMAIN_NAME, SCF_TYPE_ASTRING, 0, SMB_CF_NOTINIT}, - {SMBD_PG_NAME, SMB_CD_DOMAIN_SRV, SCF_TYPE_ASTRING, 0, SMB_CF_NOTINIT}, + {SMB_CI_DOMAIN_SID, "domain_sid", SCF_TYPE_ASTRING, 0}, + {SMB_CI_DOMAIN_MEMB, "domain_member", SCF_TYPE_BOOLEAN, 0}, + {SMB_CI_DOMAIN_NAME, "domain_name", SCF_TYPE_ASTRING, 0}, + {SMB_CI_DOMAIN_SRV, "pdc", SCF_TYPE_ASTRING, 0}, /* WINS configuration */ - {SMBD_PG_NAME, SMB_CD_WINS_SRV1, SCF_TYPE_ASTRING, 0, SMB_CF_NOTINIT}, - {SMBD_PG_NAME, SMB_CD_WINS_SRV2, SCF_TYPE_ASTRING, 0, SMB_CF_NOTINIT}, - {SMBD_PG_NAME, SMB_CD_WINS_EXCL, SCF_TYPE_ASTRING, 0, SMB_CF_NOTINIT}, + {SMB_CI_WINS_SRV1, "wins_server_1", SCF_TYPE_ASTRING, 0}, + {SMB_CI_WINS_SRV2, "wins_server_2", SCF_TYPE_ASTRING, 0}, + {SMB_CI_WINS_EXCL, "wins_exclude", SCF_TYPE_ASTRING, 0}, /* RPC services configuration */ - {SMBD_PG_NAME, SMB_CD_SRVSVC_SHRSET_ENABLE, - SCF_TYPE_BOOLEAN, 0, SMB_CF_NOTINIT}, - {SMBD_PG_NAME, SMB_CD_LOGR_ENABLE, SCF_TYPE_BOOLEAN, 0, SMB_CF_NOTINIT}, - {SMBD_PG_NAME, SMB_CD_MLRPC_KALIVE, - SCF_TYPE_INTEGER, 0, SMB_CF_NOTINIT}, + {SMB_CI_SRVSVC_SHRSET_ENABLE, "srvsvc_sharesetinfo_enable", + SCF_TYPE_BOOLEAN, 0}, + {SMB_CI_MLRPC_KALIVE, "mlrpc_keep_alive_interval", + SCF_TYPE_INTEGER, 0}, /* Kmod specific configuration */ - {SMBD_PG_NAME, SMB_CD_MAX_BUFSIZE, SCF_TYPE_INTEGER, 0, SMB_CF_NOTINIT}, - {SMBD_PG_NAME, SMB_CD_MAX_WORKERS, SCF_TYPE_INTEGER, 0, SMB_CF_NOTINIT}, - {SMBD_PG_NAME, SMB_CD_MAX_CONNECTIONS, - SCF_TYPE_INTEGER, 0, SMB_CF_NOTINIT}, - {SMBD_PG_NAME, SMB_CD_KEEPALIVE, SCF_TYPE_INTEGER, 0, SMB_CF_NOTINIT}, - {SMBD_PG_NAME, SMB_CD_RESTRICT_ANON, - SCF_TYPE_BOOLEAN, 0, SMB_CF_NOTINIT}, - - {SMBD_PG_NAME, SMB_CD_SIGNING_ENABLE, - SCF_TYPE_BOOLEAN, 0, SMB_CF_NOTINIT}, - {SMBD_PG_NAME, SMB_CD_SIGNING_REQD, - SCF_TYPE_BOOLEAN, 0, SMB_CF_NOTINIT}, - {SMBD_PG_NAME, SMB_CD_SIGNING_CHECK, - SCF_TYPE_BOOLEAN, 0, SMB_CF_NOTINIT}, + {SMB_CI_MAX_BUFSIZE, "max_bufsize", SCF_TYPE_INTEGER, 0}, + {SMB_CI_MAX_WORKERS, "max_workers", SCF_TYPE_INTEGER, 0}, + {SMB_CI_MAX_CONNECTIONS, "max_connections", SCF_TYPE_INTEGER, 0}, + {SMB_CI_KEEPALIVE, "keep_alive", SCF_TYPE_INTEGER, 0}, + {SMB_CI_RESTRICT_ANON, "restrict_anonymous", SCF_TYPE_BOOLEAN, 0}, + + {SMB_CI_SIGNING_ENABLE, "signing_enabled", SCF_TYPE_BOOLEAN, 0}, + {SMB_CI_SIGNING_REQD, "signing_required", SCF_TYPE_BOOLEAN, 0}, + {SMB_CI_SIGNING_CHECK, "signing_check", SCF_TYPE_BOOLEAN, 0}, /* Kmod tuning configuration */ - {SMBD_PG_NAME, SMB_CD_FLUSH_REQUIRED, - SCF_TYPE_BOOLEAN, 0, SMB_CF_NOTINIT}, - {SMBD_PG_NAME, SMB_CD_SYNC_ENABLE, SCF_TYPE_BOOLEAN, 0, SMB_CF_NOTINIT}, - {SMBD_PG_NAME, SMB_CD_DIRSYMLINK_DISABLE, - SCF_TYPE_BOOLEAN, 0, SMB_CF_NOTINIT}, - {SMBD_PG_NAME, SMB_CD_ANNONCE_QUOTA, - SCF_TYPE_BOOLEAN, 0, SMB_CF_NOTINIT}, + {SMB_CI_FLUSH_REQUIRED, "flush_required", SCF_TYPE_BOOLEAN, 0}, + {SMB_CI_SYNC_ENABLE, "sync_enable", SCF_TYPE_BOOLEAN, 0}, + {SMB_CI_DIRSYMLINK_DISABLE, "dir_symlink_disable", SCF_TYPE_BOOLEAN, 0}, + {SMB_CI_ANNONCE_QUOTA, "announce_quota", SCF_TYPE_BOOLEAN, 0}, /* SMBd configuration */ - {SMBD_PG_NAME, SMB_CD_SECURITY, SCF_TYPE_ASTRING, 0, SMB_CF_NOTINIT}, - {SMBD_PG_NAME, SMB_CD_NBSCOPE, SCF_TYPE_ASTRING, 0, SMB_CF_NOTINIT}, - {SMBD_PG_NAME, SMB_CD_SYS_CMNT, SCF_TYPE_ASTRING, 0, SMB_CF_NOTINIT}, - {SMBD_PG_NAME, SMB_CD_LM_LEVEL, SCF_TYPE_INTEGER, 0, SMB_CF_NOTINIT}, - {SMBD_PG_NAME, SMB_CD_MSDCS_DISABLE, - SCF_TYPE_BOOLEAN, 0, SMB_CF_NOTINIT}, + {SMB_CI_SECURITY, "security", SCF_TYPE_ASTRING, 0}, + {SMB_CI_NBSCOPE, "netbios_scope", SCF_TYPE_ASTRING, 0}, + {SMB_CI_SYS_CMNT, "system_comment", SCF_TYPE_ASTRING, 0}, + {SMB_CI_LM_LEVEL, "lmauth_level", SCF_TYPE_INTEGER, 0}, /* ADS Configuration */ - {SMBD_PG_NAME, SMB_CD_ADS_ENABLE, SCF_TYPE_BOOLEAN, 0, SMB_CF_NOTINIT}, - {SMBD_PROTECTED_PG_NAME, SMB_CD_ADS_USER, - SCF_TYPE_ASTRING, 0, SMB_CF_NOTINIT}, - {SMBD_PROTECTED_PG_NAME, SMB_CD_ADS_PASSWD, - SCF_TYPE_ASTRING, 0, SMB_CF_NOTINIT}, - {SMBD_PG_NAME, SMB_CD_ADS_DOMAIN, SCF_TYPE_ASTRING, 0, SMB_CF_NOTINIT}, - {SMBD_PG_NAME, SMB_CD_ADS_USER_CONTAINER, - SCF_TYPE_ASTRING, 0, SMB_CF_NOTINIT}, - {SMBD_PG_NAME, SMB_CD_ADS_SITE, SCF_TYPE_ASTRING, 0, SMB_CF_NOTINIT}, - {SMBD_PG_NAME, SMB_CD_ADS_IPLOOKUP, - SCF_TYPE_BOOLEAN, 0, SMB_CF_NOTINIT}, + {SMB_CI_ADS_SITE, "ads_site", SCF_TYPE_ASTRING, 0}, /* Dynamic DNS */ - {SMBD_PG_NAME, SMB_CD_DYNDNS_ENABLE, - SCF_TYPE_BOOLEAN, 0, SMB_CF_NOTINIT}, - {SMBD_PG_NAME, SMB_CD_DYNDNS_RETRY_COUNT, - SCF_TYPE_INTEGER, 0, SMB_CF_NOTINIT}, - {SMBD_PG_NAME, SMB_CD_DYNDNS_RETRY_SEC, - SCF_TYPE_INTEGER, 0, SMB_CF_NOTINIT}, - - {SMBD_PROTECTED_PG_NAME, SMB_CD_MACHINE_PASSWD, - SCF_TYPE_ASTRING, 0, SMB_CF_NOTINIT} + {SMB_CI_DYNDNS_ENABLE, "ddns_enable", SCF_TYPE_BOOLEAN, 0}, + + {SMB_CI_MACHINE_PASSWD, "machine_passwd", SCF_TYPE_ASTRING, + SMB_CF_PROTECTED} /* SMB_CI_MAX */ }; +static smb_cfg_param_t *smb_config_getent(smb_cfg_id_t); + static boolean_t smb_is_base64(unsigned char c); static char *smb_base64_encode(char *str_to_encode); static char *smb_base64_decode(char *encoded_str); -static int smb_config_update(smb_cfg_param_t *cfg, char *value); -static int smb_config_save_all(); -static int smb_config_save(char *pgname); + +char * +smb_config_getname(smb_cfg_id_t id) +{ + smb_cfg_param_t *cfg; + cfg = smb_config_getent(id); + return (cfg->sc_name); +} static boolean_t smb_is_base64(unsigned char c) @@ -321,105 +278,6 @@ smb_base64_decode(char *encoded_str) return (ret); } -/* - * Basically commit the transaction. - */ -static int -smb_config_saveenv(smb_scfhandle_t *handle) -{ - int ret = 0; - - ret = smb_smf_end_transaction(handle); - - smb_smf_scf_fini(handle); - return (ret); -} - -/* - * smb_config_getenv - * - * Get the property value from SMF. - */ -char * -smb_config_getenv(smb_cfg_id_t id) -{ - smb_scfhandle_t *handle; - char *value; - - if ((value = malloc(MAX_VALUE_BUFLEN * sizeof (char))) == NULL) - return (NULL); - - handle = smb_smf_scf_init(SMBD_FMRI_PREFIX); - if (handle == NULL) { - free(value); - return (NULL); - } - - (void) smb_smf_create_service_pgroup(handle, smb_cfg_table[id].sc_pg); - - if (smb_smf_get_property(handle, smb_cfg_table[id].sc_type, - smb_cfg_table[id].sc_name, value, - sizeof (char) * MAX_VALUE_BUFLEN) != 0) { - smb_smf_scf_fini(handle); - free(value); - return (NULL); - } - - smb_smf_scf_fini(handle); - return (value); -} - -/* - * smb_config_getenv_dec - * - * For protected property, the value obtained from SMF will be decoded. - * The decoded property value will be returned. - * - * This function should only be called by smb_config_load to populate - * the SMB config cache. - */ -static char * -smb_config_getenv_dec(smb_cfg_id_t id) -{ - smb_scfhandle_t *handle; - char *value; - char *dec; - - if ((value = malloc(MAX_VALUE_BUFLEN * sizeof (char))) == NULL) - return (NULL); - - handle = smb_smf_scf_init(SMBD_FMRI_PREFIX); - if (handle == NULL) { - free(value); - return (NULL); - } - - (void) smb_smf_create_service_pgroup(handle, smb_cfg_table[id].sc_pg); - - if (smb_smf_get_property(handle, smb_cfg_table[id].sc_type, - smb_cfg_table[id].sc_name, value, - sizeof (char) * MAX_VALUE_BUFLEN) != 0) { - smb_smf_scf_fini(handle); - free(value); - return (NULL); - } - smb_smf_scf_fini(handle); - if (strcmp(smb_cfg_table[id].sc_pg, SMBD_PROTECTED_PG_NAME)) - return (value); - - if (!value) - return (NULL); - - if (*value == '\0') { - free(value); - return (NULL); - } - - dec = smb_base64_decode(value); - free(value); - return (dec); -} - static char * smb_config_getenv_generic(char *name, char *svc_fmri_prefix, char *svc_propgrp) { @@ -449,7 +307,7 @@ smb_config_getenv_generic(char *name, char *svc_fmri_prefix, char *svc_propgrp) } -int +static int smb_config_setenv_generic(char *svc_fmri_prefix, char *svc_propgrp, char *name, char *value) { @@ -480,495 +338,302 @@ smb_config_setenv_generic(char *svc_fmri_prefix, char *svc_propgrp, } /* - * smb_config_setenv + * smb_config_getstr * - * For protected properties, the value will be encoded using base64 - * algorithm. The encoded string will be stored in SMF. + * Fetch the specified string configuration item from SMF */ int -smb_config_setenv(smb_cfg_id_t id, char *value) +smb_config_getstr(smb_cfg_id_t id, char *cbuf, int bufsz) { - smb_scfhandle_t *handle = NULL; - char *enc = NULL; - int is_protected = 0; + smb_scfhandle_t *handle; + smb_cfg_param_t *cfg; + int rc = SMBD_SMF_OK; - if ((id >= SMB_CI_MAX) || (id < 0)) { - return (1); - } + *cbuf = '\0'; + cfg = smb_config_getent(id); + assert(cfg->sc_type == SCF_TYPE_ASTRING); handle = smb_smf_scf_init(SMBD_FMRI_PREFIX); - if (handle == NULL) { - return (1); - } + if (handle == NULL) + return (SMBD_SMF_SYSTEM_ERR); - (void) smb_smf_create_service_pgroup(handle, smb_cfg_table[id].sc_pg); + if (cfg->sc_flags & SMB_CF_PROTECTED) { + char protbuf[SMB_ENC_LEN]; + char *tmp; - if (smb_smf_start_transaction(handle) != SMBD_SMF_OK) { - smb_smf_scf_fini(handle); - return (1); - } + if ((rc = smb_smf_create_service_pgroup(handle, + SMBD_PROTECTED_PG_NAME)) != SMBD_SMF_OK) + goto error; - if (strcmp(smb_cfg_table[id].sc_pg, SMBD_PROTECTED_PG_NAME) == 0) { - if ((value == NULL) || (*value == '\0')) { - (void) smb_smf_end_transaction(handle); - smb_smf_scf_fini(handle); - return (1); - } + if ((rc = smb_smf_get_string_property(handle, cfg->sc_name, + protbuf, sizeof (protbuf))) != SMBD_SMF_OK) + goto error; - if ((enc = smb_base64_encode(value)) == NULL) { - (void) smb_smf_end_transaction(handle); - smb_smf_scf_fini(handle); - return (1); + if (*protbuf != '\0') { + tmp = smb_base64_decode(protbuf); + (void) strlcpy(cbuf, tmp, bufsz); + free(tmp); } - - is_protected = 1; - } - - if (smb_smf_set_property(handle, smb_cfg_table[id].sc_type, - smb_cfg_table[id].sc_name, is_protected ? enc : value) - != SMBD_SMF_OK) { - if (enc) - free(enc); - (void) smb_smf_end_transaction(handle); - smb_smf_scf_fini(handle); - return (1); - } - - if (enc) - free(enc); - - if (smb_smf_end_transaction(handle) != SMBD_SMF_OK) { - smb_smf_scf_fini(handle); - return (1); + } else { + rc = smb_smf_create_service_pgroup(handle, SMBD_PG_NAME); + if (rc == SMBD_SMF_OK) + rc = smb_smf_get_string_property(handle, cfg->sc_name, + cbuf, bufsz); } +error: smb_smf_scf_fini(handle); - return (0); -} - -static void -smb_config_setenv_trans(smb_scfhandle_t *handle, int type, - char *name, char *value) -{ - if (smb_smf_set_property(handle, type, name, value) != SMBD_SMF_OK) { - syslog(LOG_ERR, "Failed to save service property %s", name); - } + return (rc); } /* - * smb_config_setenv_trans_protected + * smb_config_getnum * - * This function should only be called to set protected properties - * in SMF. The argument 'value' will be encoded using base64 algorithm. - * The encoded string will be stored in SMF. + * Returns the value of a numeric config param. */ -static void -smb_config_setenv_trans_protected(smb_scfhandle_t *handle, char *name, - char *value) -{ - char *enc; - - if ((value == NULL) || (*value == '\0')) - return; - - if ((enc = smb_base64_encode(value)) == NULL) - return; - - if (smb_smf_set_string_property(handle, name, enc) != SMBD_SMF_OK) { - syslog(LOG_ERR, "Failed to save service protected property" - " %s", name); - } - - free(enc); -} - int -smb_config_unsetenv(smb_cfg_id_t id) +smb_config_getnum(smb_cfg_id_t id, int64_t *cint) { - smb_scfhandle_t *handle = NULL; - int ret = 1; + smb_scfhandle_t *handle; + smb_cfg_param_t *cfg; + int rc = SMBD_SMF_OK; - handle = smb_smf_scf_init(SMBD_FMRI_PREFIX); - if (handle == NULL) { - return (ret); - } + *cint = 0; + cfg = smb_config_getent(id); + assert(cfg->sc_type == SCF_TYPE_INTEGER); - (void) smb_smf_create_service_pgroup(handle, smb_cfg_table[id].sc_pg); - if (smb_smf_start_transaction(handle) != SMBD_SMF_OK) { - smb_smf_scf_fini(handle); - return (ret); - } - ret = smb_smf_delete_property(handle, smb_cfg_table[id].sc_name); - (void) smb_smf_end_transaction(handle); + handle = smb_smf_scf_init(SMBD_FMRI_PREFIX); + if (handle == NULL) + return (SMBD_SMF_SYSTEM_ERR); + rc = smb_smf_create_service_pgroup(handle, SMBD_PG_NAME); + if (rc == SMBD_SMF_OK) + rc = smb_smf_get_integer_property(handle, cfg->sc_name, cint); smb_smf_scf_fini(handle); - return (ret); -} -static int -smb_config_unsetenv_trans(smb_scfhandle_t *handle, char *name) -{ - return (smb_smf_delete_property(handle, name)); + return (rc); } /* - * smb_config_load + * smb_config_getbool * - * Loads all the CIFS configuration parameters and sets up the - * config table. + * Returns the value of a boolean config param. */ -int -smb_config_load() +boolean_t +smb_config_getbool(smb_cfg_id_t id) { - smb_cfg_id_t id; + smb_scfhandle_t *handle; smb_cfg_param_t *cfg; - char *value; + int rc = SMBD_SMF_OK; + uint8_t vbool; - (void) rw_rdlock(&smb_cfg_rwlk); - for (id = 0; id < SMB_CI_MAX; id++) { - value = smb_config_getenv_dec(id); - cfg = &smb_cfg_table[id]; - /* - * enval == 0 could mean two things, either the - * config param is not defined, or it has been - * removed. If the variable has already been defined - * and now enval is 0, it should be removed, otherwise - * we don't need to do anything in this case. - */ - if ((cfg->sc_flags & SMB_CF_DEFINED) || value) { - if (smb_config_update(cfg, value) != 0) { - (void) rw_unlock(&smb_cfg_rwlk); - if (value) - free(value); - return (1); - } - } - if (value) { - free(value); - } - } + cfg = smb_config_getent(id); + assert(cfg->sc_type == SCF_TYPE_BOOLEAN); - (void) rw_unlock(&smb_cfg_rwlk); + handle = smb_smf_scf_init(SMBD_FMRI_PREFIX); + if (handle == NULL) + return (B_FALSE); + + rc = smb_smf_create_service_pgroup(handle, SMBD_PG_NAME); + if (rc == SMBD_SMF_OK) + rc = smb_smf_get_boolean_property(handle, cfg->sc_name, &vbool); + smb_smf_scf_fini(handle); - return (0); + return ((rc == SMBD_SMF_OK) ? (vbool == 1) : B_FALSE); } /* * smb_config_get * - * Returns value of the specified config param. - * The return value is a string pointer to the locally - * allocated memory if the config param is defined - * otherwise it would be NULL. - * - * This function MUST be called after a smb_config_rd/wrlock - * function. Caller MUST NOT modify the returned buffer directly. + * This function returns the value of the requested config + * iterm regardless of its type in string format. This should + * be used when the config item type is not known by the caller. */ -char * -smb_config_get(smb_cfg_id_t id) +int +smb_config_get(smb_cfg_id_t id, char *cbuf, int bufsz) { - if (id < SMB_CI_MAX) - return (smb_cfg_table[id].sc_value); + smb_cfg_param_t *cfg; + int64_t cint; + int rc; - return (0); -} + cfg = smb_config_getent(id); + switch (cfg->sc_type) { + case SCF_TYPE_ASTRING: + return (smb_config_getstr(id, cbuf, bufsz)); -/* - * smb_config_getstr - * - * Returns value of the specified config param. - * The returned pointer never will be NULL if the given - * 'id' is valid. If the config param is not defined its - * default value will be returned. - * - * This function MUST be called after a smb_config_rd/wrlock - * function. Caller MUST NOT modify the returned buffer directly. - */ -char * -smb_config_getstr(smb_cfg_id_t id) -{ - smb_cfg_param_t *cfg; + case SCF_TYPE_INTEGER: + rc = smb_config_getnum(id, &cint); + if (rc == SMBD_SMF_OK) + (void) snprintf(cbuf, bufsz, "%lld", cint); + return (rc); - if (id < SMB_CI_MAX) { - cfg = &smb_cfg_table[id]; - if (cfg->sc_value) - return (cfg->sc_value); + case SCF_TYPE_BOOLEAN: + if (smb_config_getbool(id)) + (void) strlcpy(cbuf, "true", bufsz); + else + (void) strlcpy(cbuf, "false", bufsz); + return (SMBD_SMF_OK); } - return (NULL); + return (SMBD_SMF_INVALID_ARG); } /* - * smb_config_getnum + * smb_config_setstr * - * Returns the value of a numeric config param. - * If the config param is not defined it'll return the - * default value. - * - * This function MUST be called after a smb_config_rd/wrlock - * function. + * Set the specified config param with the given + * value. */ -uint32_t -smb_config_getnum(smb_cfg_id_t id) +int +smb_config_setstr(smb_cfg_id_t id, char *value) { + smb_scfhandle_t *handle; smb_cfg_param_t *cfg; - char *strval = NULL; + int rc = SMBD_SMF_OK; + boolean_t protected; + char *tmp = NULL; + char *pg; - if (id < SMB_CI_MAX) { - cfg = &smb_cfg_table[id]; - if (cfg->sc_value) - strval = cfg->sc_value; + cfg = smb_config_getent(id); + assert(cfg->sc_type == SCF_TYPE_ASTRING); - if (strval) - return (strtol(strval, 0, 10)); + if (cfg->sc_flags & SMB_CF_PROTECTED) { + pg = SMBD_PROTECTED_PG_NAME; + protected = B_TRUE; + } else { + pg = SMBD_PG_NAME; + protected = B_FALSE; } - return (0); -} + handle = smb_smf_scf_init(SMBD_FMRI_PREFIX); + if (handle == NULL) + return (SMBD_SMF_SYSTEM_ERR); -/* - * smb_config_getyorn - * - * Returns the value of a yes/no config param. - * Returns 1 is config is set to "yes", otherwise 0. - * - * This function MUST be called after a smb_config_rd/wrlock - * function. - */ -int -smb_config_getyorn(smb_cfg_id_t id) -{ - char *val; + rc = smb_smf_create_service_pgroup(handle, pg); + if (rc == SMBD_SMF_OK) + rc = smb_smf_start_transaction(handle); - val = smb_config_get(id); - if (val) { - if (strcasecmp(val, "true") == 0) - return (1); + if (rc != SMBD_SMF_OK) { + smb_smf_scf_fini(handle); + return (rc); } - return (0); -} - -/* - * smb_config_set - * - * Set/update the specified config param with the given - * value. If the value is NULL the config param will be - * unset as if it is not defined. - * - * This function MUST be called after a smb_config_wrlock - * function. - */ -int -smb_config_set(smb_cfg_id_t id, char *value) -{ - smb_cfg_param_t *cfg; - int rc = 0; + if (protected && value && (*value != '\0')) { + if ((tmp = smb_base64_encode(value)) == NULL) { + (void) smb_smf_end_transaction(handle); + smb_smf_scf_fini(handle); + return (SMBD_SMF_NO_MEMORY); + } - if (id < SMB_CI_MAX) { - cfg = &smb_cfg_table[id]; - rc = smb_config_update(cfg, value); - if (rc == 0) - cfg->sc_flags |= SMB_CF_MODIFIED; - return (rc); + value = tmp; } - return (1); + rc = smb_smf_set_string_property(handle, cfg->sc_name, value); + + free(tmp); + (void) smb_smf_end_transaction(handle); + smb_smf_scf_fini(handle); + return (rc); } /* * smb_config_setnum * - * Set/update the specified config param with the given - * value. This is used for numeric config params. The given - * number will be converted to string before setting the - * config param. - * - * This function MUST be called after a smb_config_wrlock - * function. + * Sets a numeric configuration iterm */ int -smb_config_setnum(smb_cfg_id_t id, uint32_t num) +smb_config_setnum(smb_cfg_id_t id, int64_t value) { + smb_scfhandle_t *handle; smb_cfg_param_t *cfg; - char value[32]; - int rc = 0; + int rc = SMBD_SMF_OK; - if (id < SMB_CI_MAX) { - cfg = &smb_cfg_table[id]; - (void) snprintf(value, sizeof (value), "%u", num); - rc = smb_config_update(cfg, value); - if (rc == 0) - cfg->sc_flags |= SMB_CF_MODIFIED; - return (rc); - } - - return (1); -} + cfg = smb_config_getent(id); + assert(cfg->sc_type == SCF_TYPE_INTEGER); -/* - * smb_config_rdlock - * - * Lock the config table for read access. - * This function MUST be called before any kind of - * read access to the config table i.e. all flavors of - * smb_config_get function - */ -void -smb_config_rdlock() -{ - (void) rw_rdlock(&smb_cfg_rwlk); - lock_type = SMB_CL_READ; -} - -/* - * smb_config_wrlock - * - * Lock the config table for write access. - * This function MUST be called before any kind of - * write access to the config table i.e. all flavors of - * smb_config_set function - */ -void -smb_config_wrlock() -{ - (void) rw_wrlock(&smb_cfg_rwlk); - lock_type = SMB_CL_WRITE; -} - -/* - * smb_config_wrlock - * - * Unlock the config table. - * If the config table has been locked for write access - * smb_config_save_all() will be called to save the changes - * before unlocking the table. - * - * This function MUST be called after smb_config_rd/wrlock - */ -void -smb_config_unlock() -{ - if (lock_type == SMB_CL_WRITE) - (void) smb_config_save_all(); - (void) rw_unlock(&smb_cfg_rwlk); -} + handle = smb_smf_scf_init(SMBD_FMRI_PREFIX); + if (handle == NULL) + return (SMBD_SMF_SYSTEM_ERR); -/* - * smb_config_save_all - * - * Save all modified parameters to SMF. - */ -static int -smb_config_save_all() -{ - int rc; + rc = smb_smf_create_service_pgroup(handle, SMBD_PG_NAME); + if (rc == SMBD_SMF_OK) + rc = smb_smf_start_transaction(handle); - if ((rc = smb_config_save(SMBD_PG_NAME)) != 0) + if (rc != SMBD_SMF_OK) { + smb_smf_scf_fini(handle); return (rc); + } - return (smb_config_save(SMBD_PROTECTED_PG_NAME)); + rc = smb_smf_set_integer_property(handle, cfg->sc_name, value); + + (void) smb_smf_end_transaction(handle); + smb_smf_scf_fini(handle); + return (rc); } /* - * smb_config_save + * smb_config_setbool * - * Scan the config table and call smb_config_setenv/smb_config_unsetenv - * for params in the specified property group that has been modified. - * When the scan is finished, smb_config_saveenv() will be called to - * make the changes persistent. + * Sets a boolean configuration iterm */ -static int -smb_config_save(char *pgname) +int +smb_config_setbool(smb_cfg_id_t id, boolean_t value) { - smb_cfg_id_t id; + smb_scfhandle_t *handle; smb_cfg_param_t *cfg; - smb_scfhandle_t *handle = NULL; - int dorefresh = 0; + int rc = SMBD_SMF_OK; + + cfg = smb_config_getent(id); + assert(cfg->sc_type == SCF_TYPE_BOOLEAN); handle = smb_smf_scf_init(SMBD_FMRI_PREFIX); - if (handle == NULL) { - syslog(LOG_ERR, "smbd: cannot save configuration"); - return (1); - } + if (handle == NULL) + return (SMBD_SMF_SYSTEM_ERR); - (void) smb_smf_create_service_pgroup(handle, pgname); - if (smb_smf_start_transaction(handle) != SMBD_SMF_OK) { - syslog(LOG_ERR, "smbd: cannot save configuration"); - return (1); - } + rc = smb_smf_create_service_pgroup(handle, SMBD_PG_NAME); + if (rc == SMBD_SMF_OK) + rc = smb_smf_start_transaction(handle); - for (id = 0; id < SMB_CI_MAX; id++) { - cfg = &smb_cfg_table[id]; - if (strcmp(cfg->sc_pg, pgname)) - continue; - - if (cfg->sc_flags & SMB_CF_MODIFIED) { - if (cfg->sc_value) { - if (strcmp(pgname, SMBD_PG_NAME) == 0) - smb_config_setenv_trans(handle, - cfg->sc_type, cfg->sc_name, - cfg->sc_value); - else - smb_config_setenv_trans_protected( - handle, cfg->sc_name, - cfg->sc_value); - } else { - (void) smb_config_unsetenv_trans(handle, - cfg->sc_name); - } - cfg->sc_flags &= ~SMB_CF_MODIFIED; - dorefresh = 1; - } + if (rc != SMBD_SMF_OK) { + smb_smf_scf_fini(handle); + return (rc); } - if (smb_config_saveenv(handle) != 0) { - syslog(LOG_ERR, "smbd: cannot save configuration"); - return (1); - } - if (dorefresh) - (void) smf_refresh_instance(SMBD_DEFAULT_INSTANCE_FMRI); - return (0); + rc = smb_smf_set_boolean_property(handle, cfg->sc_name, value); + + (void) smb_smf_end_transaction(handle); + smb_smf_scf_fini(handle); + return (rc); } /* - * smb_config_update + * smb_config_set * - * Updates the specified config param with the given value. - * This function is called both on (re)load and set. + * This function sets the value of the specified config + * iterm regardless of its type in string format. This should + * be used when the config item type is not known by the caller. */ -static int -smb_config_update(smb_cfg_param_t *cfg, char *value) +int +smb_config_set(smb_cfg_id_t id, char *value) { - char *curval; - int rc = 0; - int len; - - if (value) { - len = strlen(value); - if (cfg->sc_value) { - curval = (char *)realloc(cfg->sc_value, - (len + 1)); - } else { - curval = (char *)malloc(len + 1); - } + smb_cfg_param_t *cfg; + int64_t cint; - if (curval) { - cfg->sc_value = curval; - (void) strcpy(cfg->sc_value, value); - cfg->sc_flags |= SMB_CF_DEFINED; - } else { - rc = 1; - } - } else if (cfg->sc_value) { - free(cfg->sc_value); - cfg->sc_value = NULL; - cfg->sc_flags &= ~SMB_CF_DEFINED; + cfg = smb_config_getent(id); + switch (cfg->sc_type) { + case SCF_TYPE_ASTRING: + return (smb_config_setstr(id, value)); + + case SCF_TYPE_INTEGER: + cint = atoi(value); + return (smb_config_setnum(id, cint)); + + case SCF_TYPE_BOOLEAN: + return (smb_config_setbool(id, strcasecmp(value, "true") == 0)); } - return (rc); + return (SMBD_SMF_INVALID_ARG); } - uint8_t smb_config_get_fg_flag() { @@ -1072,9 +737,9 @@ smb_config_secmode_tostr(int secmode) int smb_config_get_secmode() { - char *p; + char p[16]; - p = smb_config_getstr(SMB_CI_SECURITY); + (void) smb_config_getstr(SMB_CI_SECURITY, p, sizeof (p)); return (smb_config_secmode_fromstr(p)); } @@ -1084,5 +749,18 @@ smb_config_set_secmode(int secmode) char *p; p = smb_config_secmode_tostr(secmode); - return (smb_config_set(SMB_CI_SECURITY, p)); + return (smb_config_setstr(SMB_CI_SECURITY, p)); +} + +static smb_cfg_param_t * +smb_config_getent(smb_cfg_id_t id) +{ + int i; + + for (i = 0; i < SMB_CI_MAX; i++) + if (smb_cfg_table[i].sc_id == id) + return (&smb_cfg_table[id]); + + assert(0); + return (NULL); } diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_domain.c b/usr/src/lib/smbsrv/libsmb/common/smb_domain.c index 22ea5e61fb..f57dadc806 100644 --- a/usr/src/lib/smbsrv/libsmb/common/smb_domain.c +++ b/usr/src/lib/smbsrv/libsmb/common/smb_domain.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -77,10 +77,11 @@ int nt_domain_init(char *resource_domain, uint32_t secmode) { nt_domain_t *domain; - nt_sid_t *sid; - char *sidstr; + nt_sid_t *sid = NULL; + char sidstr[128]; char *lsidstr; char hostname[MAXHOSTNAMELEN]; + int rc; if (rwlock_init(&nt_domain_lock, USYNC_THREAD, NULL)) return (SMB_DOMAIN_NODOMAIN_SID); @@ -112,17 +113,18 @@ nt_domain_init(char *resource_domain, uint32_t secmode) (void) nt_domain_add(domain); free(sid); - smb_config_rdlock(); - sidstr = smb_config_get(SMB_CI_DOMAIN_SID); - if (sidstr) { + sid = NULL; + rc = smb_config_getstr(SMB_CI_DOMAIN_SID, sidstr, + sizeof (sidstr)); + if (rc == SMBD_SMF_OK) sid = nt_sid_strtosid(sidstr); - smb_config_unlock(); + if (nt_sid_is_valid(sid)) { domain = nt_domain_new(NT_DOMAIN_PRIMARY, resource_domain, sid); (void) nt_domain_add(domain); free(sid); } else { - smb_config_unlock(); + free(sid); (void) rwlock_destroy(&nt_domain_lock); return (SMB_DOMAIN_NODOMAIN_SID); } @@ -198,9 +200,7 @@ nt_domain_add(nt_domain_t *new_domain) if (new_domain->type == NT_DOMAIN_PRIMARY) { sidstr = nt_sid_format(new_domain->sid); - smb_config_wrlock(); - (void) smb_config_set(SMB_CI_DOMAIN_SID, sidstr); - smb_config_unlock(); + (void) smb_config_setstr(SMB_CI_DOMAIN_SID, sidstr); free(sidstr); } (void) rw_unlock(&nt_domain_lock); diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_door_client.c b/usr/src/lib/smbsrv/libsmb/common/smb_door_client.c index 06eeac365c..7884b972a5 100644 --- a/usr/src/lib/smbsrv/libsmb/common/smb_door_client.c +++ b/usr/src/lib/smbsrv/libsmb/common/smb_door_client.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -36,7 +36,6 @@ #include <strings.h> #include <stdlib.h> #include <errno.h> -#include <unistd.h> #include <smbsrv/smbinfo.h> #include <smbsrv/wintypes.h> @@ -54,7 +53,6 @@ static char *smbd_desc[] = { "SmbdGetParam", "SmbdSetParam", "SmbdNetbiosReconfig", - "SmbdAdsDomainChanged", 0 }; @@ -411,95 +409,3 @@ smbd_get_security_mode(int *mode) *mode = smb_config_secmode_fromstr(buf); return (rc); } - -/* - * smb_ads_domain_change_notify - * - * When ADS domain has changed, this function is called to clear the - * ADS_HOST_INFO cache and remove the old keys from the Kerberos keytab. - */ -int -smb_ads_domain_change_notify(char *dom) -{ - door_arg_t arg; - char *buf; - uint32_t used; - smb_dr_ctx_t *dec_ctx; - smb_dr_ctx_t *enc_ctx; - int status; - int rc; - int opcode = SMBD_DOOR_ADS_DOMAIN_CHANGED; - - if (smbd_door_open(opcode) == -1) { - syslog(LOG_ERR, "%s: cannot open the door", smbd_desc[opcode]); - return (1); - } - - buf = MEM_MALLOC("smb_door_client", SMBD_DOOR_SIZE); - if (!buf) { - syslog(LOG_ERR, "%s: resource shortage", smbd_desc[opcode]); - (void) close(smb_door_fildes); - smb_door_fildes = -1; - return (1); - } - - enc_ctx = smb_dr_encode_start(buf, SMBD_DOOR_SIZE); - if (enc_ctx == 0) { - syslog(LOG_ERR, "%s: encode start failed", smbd_desc[opcode]); - MEM_FREE("smb_door_client", buf); - (void) close(smb_door_fildes); - smb_door_fildes = -1; - return (1); - } - - smb_dr_put_uint32(enc_ctx, opcode); - smb_dr_put_string(enc_ctx, dom); - - if ((status = smb_dr_encode_finish(enc_ctx, &used)) != 0) { - syslog(LOG_ERR, "%s: Encode error %s", - smbd_desc[opcode], strerror(status)); - MEM_FREE("smb_door_client", buf); - (void) close(smb_door_fildes); - smb_door_fildes = -1; - return (1); - } - - arg.data_ptr = buf; - arg.data_size = used; - arg.desc_ptr = NULL; - arg.desc_num = 0; - arg.rbuf = buf; - arg.rsize = SMBD_DOOR_SIZE; - - if (door_call(smb_door_fildes, &arg) < 0) { - syslog(LOG_ERR, "%s: Door call failed %s", smbd_desc[opcode], - strerror(errno)); - MEM_FREE("smb_door_client", buf); - (void) close(smb_door_fildes); - smb_door_fildes = -1; - return (1); - } - - dec_ctx = smb_dr_decode_start(arg.data_ptr, arg.data_size); - if (smbd_door_check_srv_status(opcode, dec_ctx) != 0) { - MEM_FREE("smb_door_client", buf); - (void) close(smb_door_fildes); - smb_door_fildes = -1; - return (1); - } - rc = smb_dr_get_uint32(dec_ctx); - - if ((status = smb_dr_decode_finish(dec_ctx)) != 0) { - syslog(LOG_ERR, "%s: Decode error %s", - smbd_desc[opcode], strerror(status)); - MEM_FREE("smb_door_client", buf); - (void) close(smb_door_fildes); - smb_door_fildes = -1; - return (1); - } - MEM_FREE("smb_door_client", buf); - (void) close(smb_door_fildes); - smb_door_fildes = -1; - - return (rc); -} diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_group_door_encdec.c b/usr/src/lib/smbsrv/libsmb/common/smb_group_door_encdec.c deleted file mode 100644 index 0b29764926..0000000000 --- a/usr/src/lib/smbsrv/libsmb/common/smb_group_door_encdec.c +++ /dev/null @@ -1,337 +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 2007 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <stdio.h> -#include <stdlib.h> -#include <errno.h> -#include <strings.h> -#include <smbsrv/libsmb.h> -#include <smbsrv/smb_xdr.h> -#include <smbsrv/smb_door_svc.h> - -/* - * smb_grplist_mkselfrel - * - * encode: structure -> flat buffer (buffer size) - * Pre-condition: obj is non-null. - */ -static uint8_t * -smb_grplist_mkselfrel(ntgrp_list_t *obj, uint32_t *len) -{ - uint8_t *buf; - XDR xdrs; - - if (!obj) { - syslog(LOG_ERR, "smb_grplist_mkselfrel: invalid parameter"); - return (NULL); - } - *len = xdr_sizeof(xdr_ntgrp_list_t, obj); - buf = (uint8_t *)malloc(*len); - - xdrmem_create(&xdrs, (const caddr_t)buf, *len, XDR_ENCODE); - - if (!xdr_ntgrp_list_t(&xdrs, obj)) { - syslog(LOG_ERR, "smb_grplist_mkselfrel: XDR encode error"); - free(buf); - *len = 0; - buf = NULL; - } - - xdr_destroy(&xdrs); - return (buf); -} - -/* - * smb_grplist_mkabsolute - * - * decode: flat buffer -> structure - */ -static ntgrp_list_t * -smb_grplist_mkabsolute(uint8_t *buf, uint32_t len) -{ - ntgrp_list_t *obj; - XDR xdrs; - - xdrmem_create(&xdrs, (const caddr_t)buf, len, XDR_DECODE); - - if ((obj = (ntgrp_list_t *) - malloc(sizeof (ntgrp_list_t))) == 0) { - syslog(LOG_ERR, "smb_grplist_mkabsolute: resource shortage"); - xdr_destroy(&xdrs); - return (NULL); - } - bzero(obj, sizeof (ntgrp_list_t)); - if (!xdr_ntgrp_list_t(&xdrs, obj)) { - syslog(LOG_ERR, "smb_grplist_mkabsolute: XDR decode error"); - smb_group_free_list(obj, 1); - obj = NULL; - } - - xdr_destroy(&xdrs); - return (obj); -} - -/* - * smb_grpmemberlist_mkselfrel - * - * encode: structure -> flat buffer (buffer size) - * Pre-condition: obj is non-null. - */ -static uint8_t * -smb_grpmemberlist_mkselfrel(ntgrp_member_list_t *obj, uint32_t *len) -{ - uint8_t *buf; - XDR xdrs; - - if (!obj) { - syslog(LOG_ERR, - "smb_grpmemberlist_mkselfrel: invalid parameter"); - return (NULL); - } - *len = xdr_sizeof(xdr_ntgrp_member_list_t, obj); - buf = (uint8_t *)malloc(*len); - xdrmem_create(&xdrs, (const caddr_t)buf, *len, XDR_ENCODE); - if (!xdr_ntgrp_member_list_t(&xdrs, obj)) { - syslog(LOG_ERR, - "smb_grpmemberlist_mkselfrel: XDR encode error"); - free(buf); - *len = 0; - buf = NULL; - } - - xdr_destroy(&xdrs); - return (buf); -} - -/* - * ntgrp_list_mkabsolute - * - * decode: flat buffer -> structure - */ -static ntgrp_member_list_t * -smb_grpmemberlist_mkabsolute(uint8_t *buf, uint32_t len) -{ - ntgrp_member_list_t *obj = NULL; - XDR xdrs; - - xdrmem_create(&xdrs, (const caddr_t)buf, len, XDR_DECODE); - - if ((obj = (ntgrp_member_list_t *) - malloc(sizeof (ntgrp_member_list_t))) == 0) { - xdr_destroy(&xdrs); - syslog(LOG_ERR, - "smb_grpmemberlist_mkabsolute: resource shortage"); - return (NULL); - } - bzero(obj, sizeof (ntgrp_member_list_t)); - bzero(obj->members, SMB_GROUP_PER_LIST * sizeof (members_list)); - if (!xdr_ntgrp_member_list_t(&xdrs, obj)) { - syslog(LOG_ERR, - "smb_grpmemberlist_mkabsolute: XDR decode error"); - smb_group_free_memberlist(obj, 1); - obj = NULL; - } - - xdr_destroy(&xdrs); - return (obj); -} - -/* - * smb_privlist_mkselfrel - * - * encode: structure -> flat buffer (buffer size) - * Pre-condition: obj is non-null. - */ -static uint8_t * -smb_grpprivlist_mkselfrel(ntpriv_list_t *obj, uint32_t *len) -{ - uint8_t *buf; - XDR xdrs; - - if (!obj) { - syslog(LOG_ERR, - "smb_grpprivlist_mkselfrel: invalid parameter"); - return (NULL); - } - *len = xdr_sizeof(xdr_ntpriv_list_t, obj); - buf = (uint8_t *)malloc(*len); - if (!buf) { - syslog(LOG_ERR, - "smb_grpprivlist_mkselfrel: resource shortage"); - return (NULL); - } - xdrmem_create(&xdrs, (const caddr_t)buf, *len, XDR_ENCODE); - if (!xdr_ntpriv_list_t(&xdrs, obj)) { - syslog(LOG_ERR, - "smb_grpprivlist_mkselfrel: XDR encode error"); - *len = 0; - free(buf); - buf = NULL; - } - xdr_destroy(&xdrs); - return (buf); -} - -/* - * smb_privlist_mkabsolute - * - * decode: flat buffer -> structure - */ -static ntpriv_list_t * -smb_grpprivlist_mkabsolute(uint8_t *buf, uint32_t len) -{ - ntpriv_list_t *obj = NULL; - XDR xdrs; - uint32_t status; - int length = 0, num_privs = 0; - - xdrmem_create(&xdrs, (const caddr_t)buf, len, XDR_DECODE); - status = smb_group_priv_num(&num_privs); - if (status != 0) { - syslog(LOG_ERR, - "smb_grpprivlist_mkabsolute: Cannot get privlist."); - xdr_destroy(&xdrs); - return (NULL); - } - - if (num_privs > 0) { - length = sizeof (int) + (num_privs * sizeof (privs_t)); - if ((obj = (ntpriv_list_t *)malloc(length)) == 0) { - syslog(LOG_ERR, - "smb_grpprivlist_mkabsolute: resource shortage"); - xdr_destroy(&xdrs); - return (NULL); - } - } - bzero(obj, sizeof (ntpriv_list_t)); - bzero(obj->privs, num_privs * sizeof (privs_t)); - if (!xdr_ntpriv_list_t(&xdrs, obj)) { - syslog(LOG_ERR, "smb_grpprivlist_mkabsolute: XDR decode error"); - smb_group_free_privlist(obj, 1); - obj = NULL; - } - xdr_destroy(&xdrs); - return (obj); -} - -char * -smb_dr_encode_grp_list(uint32_t opcode, ntgrp_list_t *list, - size_t *len) -{ - char *buf; - smb_dr_bytes_t arg; - - arg.bytes_val = smb_grplist_mkselfrel(list, &arg.bytes_len); - - buf = smb_dr_encode_common(opcode, &arg, xdr_smb_dr_bytes_t, len); - free(arg.bytes_val); - return (buf); -} - -ntgrp_list_t * -smb_dr_decode_grp_list(char *buf, size_t len) -{ - smb_dr_bytes_t arg; - ntgrp_list_t *list; - - bzero(&arg, sizeof (smb_dr_bytes_t)); - if (smb_dr_decode_common(buf, len, xdr_smb_dr_bytes_t, &arg) - != 0) { - syslog(LOG_ERR, "smb_dr_decode_grplist: XDR decode error"); - xdr_free(xdr_smb_dr_bytes_t, (char *)&arg); - return (NULL); - } - list = smb_grplist_mkabsolute(arg.bytes_val, arg.bytes_len); - xdr_free(xdr_smb_dr_bytes_t, (char *)&arg); - return (list); -} - -char * -smb_dr_encode_grp_memberlist(uint32_t opcode, - ntgrp_member_list_t *list, size_t *len) -{ - char *buf; - smb_dr_bytes_t arg; - - arg.bytes_val = smb_grpmemberlist_mkselfrel(list, &arg.bytes_len); - - buf = smb_dr_encode_common(opcode, &arg, xdr_smb_dr_bytes_t, len); - free(arg.bytes_val); - return (buf); -} - -ntgrp_member_list_t * -smb_dr_decode_grp_memberlist(char *buf, size_t len) -{ - smb_dr_bytes_t arg; - ntgrp_member_list_t *list; - - bzero(&arg, sizeof (smb_dr_bytes_t)); - if (smb_dr_decode_common(buf, len, xdr_smb_dr_bytes_t, &arg) - != 0) { - syslog(LOG_ERR, - "smb_dr_decode_grpmemberlist: XDR decode error"); - xdr_free(xdr_smb_dr_bytes_t, (char *)&arg); - return (NULL); - } - list = smb_grpmemberlist_mkabsolute(arg.bytes_val, arg.bytes_len); - xdr_free(xdr_smb_dr_bytes_t, (char *)&arg); - return (list); -} - -char * -smb_dr_encode_grp_privlist(uint32_t opcode, - ntpriv_list_t *list, size_t *len) -{ - char *buf; - smb_dr_bytes_t arg; - - arg.bytes_val = smb_grpprivlist_mkselfrel(list, &arg.bytes_len); - - buf = smb_dr_encode_common(opcode, &arg, xdr_smb_dr_bytes_t, len); - free(arg.bytes_val); - return (buf); -} - -ntpriv_list_t * -smb_dr_decode_grp_privlist(char *buf, size_t len) -{ - smb_dr_bytes_t arg; - ntpriv_list_t *list; - - bzero(&arg, sizeof (smb_dr_bytes_t)); - if (smb_dr_decode_common(buf, len, xdr_smb_dr_bytes_t, &arg) - != 0) { - syslog(LOG_ERR, "smb_dr_decode_grp_privlist: XDR decode error"); - xdr_free(xdr_smb_dr_bytes_t, (char *)&arg); - return (NULL); - } - list = smb_grpprivlist_mkabsolute(arg.bytes_val, arg.bytes_len); - xdr_free(xdr_smb_dr_bytes_t, (char *)&arg); - return (list); -} diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_group_xdr.c b/usr/src/lib/smbsrv/libsmb/common/smb_group_xdr.c deleted file mode 100644 index 723a6471f9..0000000000 --- a/usr/src/lib/smbsrv/libsmb/common/smb_group_xdr.c +++ /dev/null @@ -1,158 +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 2007 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include <rpc/rpc.h> -#include <smbsrv/libsmb.h> - -#pragma ident "%Z%%M% %I% %E% SMI" - -/* - * This file was originally generated using rpcgen. - */ - -bool_t -xdr_ntgrp_dr_arg_t(xdrs, objp) - XDR *xdrs; - ntgrp_dr_arg_t *objp; -{ - if (!xdr_string(xdrs, &objp->gname, ~0)) - return (FALSE); - if (!xdr_string(xdrs, &objp->desc, ~0)) - return (FALSE); - if (!xdr_string(xdrs, &objp->member, ~0)) - return (FALSE); - if (!xdr_string(xdrs, &objp->newgname, ~0)) - return (FALSE); - if (!xdr_uint32_t(xdrs, &objp->privid)) - return (FALSE); - if (!xdr_uint32_t(xdrs, &objp->priv_attr)) - return (FALSE); - if (!xdr_int(xdrs, &objp->offset)) - return (FALSE); - if (!xdr_string(xdrs, &objp->scope, ~0)) - return (FALSE); - if (!xdr_int(xdrs, &objp->type)) - return (FALSE); - if (!xdr_int(xdrs, &objp->count)) - return (FALSE); - if (!xdr_uint32_t(xdrs, &objp->ntstatus)) - return (FALSE); - return (TRUE); -} - -bool_t -xdr_ntgrp_t(xdrs, objp) - XDR *xdrs; - ntgrp_t *objp; -{ - if (!xdr_uint32_t(xdrs, &objp->rid)) - return (FALSE); - if (!xdr_string(xdrs, &objp->name, ~0)) - return (FALSE); - if (!xdr_string(xdrs, &objp->desc, ~0)) - return (FALSE); - if (!xdr_string(xdrs, &objp->type, ~0)) - return (FALSE); - if (!xdr_string(xdrs, &objp->sid, ~0)) - return (FALSE); - if (!xdr_uint32_t(xdrs, &objp->attr)) - return (FALSE); - return (TRUE); -} - -bool_t -xdr_ntgrp_list_t(xdrs, objp) - XDR *xdrs; - ntgrp_list_t *objp; -{ - if (!xdr_int(xdrs, &objp->cnt)) - return (FALSE); - if (!xdr_vector(xdrs, (char *)objp->groups, SMB_GROUP_PER_LIST, - sizeof (ntgrp_t), (xdrproc_t)xdr_ntgrp_t)) - return (FALSE); - return (TRUE); -} - -bool_t -xdr_members_list(xdrs, objp) - XDR *xdrs; - members_list *objp; -{ - if (!xdr_string(xdrs, objp, ~0)) - return (FALSE); - return (TRUE); -} - -bool_t -xdr_ntgrp_member_list_t(xdrs, objp) - XDR *xdrs; - ntgrp_member_list_t *objp; -{ - if (!xdr_uint32_t(xdrs, &objp->rid)) - return (FALSE); - if (!xdr_int(xdrs, &objp->cnt)) - return (FALSE); - if (!xdr_vector(xdrs, (char *)objp->members, SMB_GROUP_PER_LIST, - sizeof (members_list), (xdrproc_t)xdr_members_list)) - return (FALSE); - return (TRUE); -} - -bool_t -xdr_ntpriv_t(xdrs, objp) - XDR *xdrs; - ntpriv_t *objp; -{ - if (!xdr_uint32_t(xdrs, &objp->id)) - return (FALSE); - if (!xdr_string(xdrs, &objp->name, ~0)) - return (FALSE); - return (TRUE); -} - -bool_t -xdr_privs_t(xdrs, objp) - XDR *xdrs; - privs_t *objp; -{ - if (!xdr_pointer(xdrs, (char **)objp, sizeof (ntpriv_t), - (xdrproc_t)xdr_ntpriv_t)) - return (FALSE); - return (TRUE); -} - -bool_t -xdr_ntpriv_list_t(xdrs, objp) - XDR *xdrs; - ntpriv_list_t *objp; -{ - if (!xdr_int(xdrs, &objp->cnt)) - return (FALSE); - if (!xdr_vector(xdrs, (char *)objp->privs, objp->cnt, - sizeof (privs_t), (xdrproc_t)xdr_privs_t)) - return (FALSE); - return (TRUE); -} diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_idmap.c b/usr/src/lib/smbsrv/libsmb/common/smb_idmap.c index f410fe3237..862bcf919d 100644 --- a/usr/src/lib/smbsrv/libsmb/common/smb_idmap.c +++ b/usr/src/lib/smbsrv/libsmb/common/smb_idmap.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -126,6 +126,43 @@ smb_idmap_getsid(uid_t id, int idtype, nt_sid_t **sid) } /* + * smb_idmap_getid + * + * Tries to get a mapping for the given SID + */ +idmap_stat +smb_idmap_getid(nt_sid_t *sid, uid_t *id, int *id_type) +{ + smb_idmap_batch_t sib; + smb_idmap_t *sim; + idmap_stat stat; + + stat = smb_idmap_batch_create(&sib, 1, SMB_IDMAP_SID2ID); + if (stat != IDMAP_SUCCESS) + return (stat); + + sim = &sib.sib_maps[0]; + sim->sim_id = id; + stat = smb_idmap_batch_getid(sib.sib_idmaph, sim, sid, *id_type); + if (stat != IDMAP_SUCCESS) { + smb_idmap_batch_destroy(&sib); + return (stat); + } + + stat = smb_idmap_batch_getmappings(&sib); + + if (stat != IDMAP_SUCCESS) { + smb_idmap_batch_destroy(&sib); + return (stat); + } + + *id_type = sim->sim_idtype; + smb_idmap_batch_destroy(&sib); + + return (IDMAP_SUCCESS); +} + +/* * smb_idmap_batch_create * * Creates and initializes the context for batch ID mapping. @@ -163,7 +200,6 @@ void smb_idmap_batch_destroy(smb_idmap_batch_t *sib) { nt_sid_t *sid; - char *domsid; int i; if (!sib) @@ -177,8 +213,7 @@ smb_idmap_batch_destroy(smb_idmap_batch_t *sib) if (!sib->sib_maps) return; - switch (sib->sib_flags) { - case SMB_IDMAP_SID2ID: + if (sib->sib_flags & SMB_IDMAP_ID2SID) { /* * SIDs are allocated only when mapping * UID/GID to SIDs @@ -188,20 +223,6 @@ smb_idmap_batch_destroy(smb_idmap_batch_t *sib) if (sid) free(sid); } - break; - case SMB_IDMAP_ID2SID: - /* - * SID prefixes are allocated only when mapping - * SIDs to UID/GID - */ - for (i = 0; i < sib->sib_nmap; i++) { - domsid = sib->sib_maps[i].sim_domsid; - if (domsid) - free(domsid); - } - break; - default: - break; } if (sib->sib_size && sib->sib_maps) { @@ -262,9 +283,11 @@ smb_idmap_batch_getid(idmap_get_handle_t *idmaph, smb_idmap_t *sim, break; default: + free(sim->sim_domsid); return (IDMAP_ERR_ARG); } + free(sim->sim_domsid); return (stat); } @@ -371,6 +394,7 @@ smb_idmap_batch_binsid(smb_idmap_batch_t *sib) return (-1); sid = nt_sid_strtosid(sim->sim_domsid); + free(sim->sim_domsid); if (sid == NULL) return (-1); diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_info.c b/usr/src/lib/smbsrv/libsmb/common/smb_info.c index d39eaf9208..918cc02acb 100644 --- a/usr/src/lib/smbsrv/libsmb/common/smb_info.c +++ b/usr/src/lib/smbsrv/libsmb/common/smb_info.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -37,6 +37,9 @@ #include <errno.h> #include <net/if.h> #include <netdb.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <resolv.h> #include <sys/sockio.h> #include <smbsrv/smbinfo.h> #include <smbsrv/netbios.h> @@ -48,85 +51,6 @@ static cond_t smbpdc_cv; extern int getdomainname(char *, int); -uint32_t -smb_get_security_mode() -{ - uint32_t mode; - - smb_config_rdlock(); - mode = smb_config_get_secmode(); - smb_config_unlock(); - - return (mode); -} - -/* - * smb_purge_domain_info - * - * Clean out the environment in preparation for joining a domain. - * This ensures that we don't have any old information lying around. - */ -void -smb_purge_domain_info(void) -{ - smb_config_wrlock(); - (void) smb_config_set(SMB_CI_DOMAIN_NAME, 0); - (void) smb_config_set(SMB_CI_DOMAIN_SID, 0); - (void) smb_config_set(SMB_CI_DOMAIN_MEMB, 0); - smb_config_unlock(); -} - -int -smb_is_domain_member(void) -{ - int is_memb; - - smb_config_rdlock(); - is_memb = smb_config_getyorn(SMB_CI_DOMAIN_MEMB); - smb_config_unlock(); - - return (is_memb); -} - -uint8_t -smb_get_fg_flag(void) -{ - uint8_t run_fg; - - smb_config_rdlock(); - run_fg = smb_config_get_fg_flag(); - smb_config_unlock(); - - return (run_fg); -} - -void -smb_set_domain_member(int set) -{ - char *member; - - smb_config_wrlock(); - member = (set) ? "true" : "false"; - (void) smb_config_set(SMB_CI_DOMAIN_MEMB, member); - smb_config_unlock(); -} - -/* - * smb_set_machine_pwd - * - * Returns 0 upon success. Otherwise, returns 1. - */ -int -smb_set_machine_pwd(char *pwd) -{ - int rc; - - smb_config_wrlock(); - rc = smb_config_set(SMB_CI_MACHINE_PASSWD, pwd); - smb_config_unlock(); - return (rc); -} - /* * smb_getdomaininfo * @@ -206,47 +130,41 @@ smb_setdomaininfo(char *domain, char *server, uint32_t ipaddr) void smb_load_kconfig(smb_kmod_cfg_t *kcfg) { - smb_config_rdlock(); + int64_t citem; + bzero(kcfg, sizeof (smb_kmod_cfg_t)); - kcfg->skc_maxbufsize = smb_config_getnum(SMB_CI_MAX_BUFSIZE); - kcfg->skc_maxworkers = smb_config_getnum(SMB_CI_MAX_WORKERS); - kcfg->skc_keepalive = smb_config_getnum(SMB_CI_KEEPALIVE); + (void) smb_config_getnum(SMB_CI_MAX_BUFSIZE, &citem); + kcfg->skc_maxbufsize = (uint32_t)citem; + (void) smb_config_getnum(SMB_CI_MAX_WORKERS, &citem); + kcfg->skc_maxworkers = (uint32_t)citem; + (void) smb_config_getnum(SMB_CI_KEEPALIVE, &citem); + kcfg->skc_keepalive = (uint32_t)citem; if ((kcfg->skc_keepalive != 0) && (kcfg->skc_keepalive < SMB_PI_KEEP_ALIVE_MIN)) kcfg->skc_keepalive = SMB_PI_KEEP_ALIVE_MIN; - kcfg->skc_restrict_anon = smb_config_getyorn(SMB_CI_RESTRICT_ANON); - - kcfg->skc_signing_enable = smb_config_getyorn(SMB_CI_SIGNING_ENABLE); - kcfg->skc_signing_required = smb_config_getyorn(SMB_CI_SIGNING_REQD); - kcfg->skc_signing_check = smb_config_getyorn(SMB_CI_SIGNING_CHECK); - kcfg->skc_oplock_enable = smb_config_getyorn(SMB_CI_OPLOCK_ENABLE); - kcfg->skc_oplock_timeout = smb_config_getnum(SMB_CI_OPLOCK_TIMEOUT); - - kcfg->skc_flush_required = smb_config_getyorn(SMB_CI_FLUSH_REQUIRED); - kcfg->skc_sync_enable = smb_config_getyorn(SMB_CI_SYNC_ENABLE); + (void) smb_config_getnum(SMB_CI_OPLOCK_TIMEOUT, &citem); + kcfg->skc_oplock_timeout = (uint32_t)citem; + (void) smb_config_getnum(SMB_CI_MAX_CONNECTIONS, &citem); + kcfg->skc_maxconnections = (uint32_t)citem; + kcfg->skc_restrict_anon = smb_config_getbool(SMB_CI_RESTRICT_ANON); + kcfg->skc_signing_enable = smb_config_getbool(SMB_CI_SIGNING_ENABLE); + kcfg->skc_signing_required = smb_config_getbool(SMB_CI_SIGNING_REQD); + kcfg->skc_signing_check = smb_config_getbool(SMB_CI_SIGNING_CHECK); + kcfg->skc_oplock_enable = smb_config_getbool(SMB_CI_OPLOCK_ENABLE); + kcfg->skc_flush_required = smb_config_getbool(SMB_CI_FLUSH_REQUIRED); + kcfg->skc_sync_enable = smb_config_getbool(SMB_CI_SYNC_ENABLE); kcfg->skc_dirsymlink_enable = - !smb_config_getyorn(SMB_CI_DIRSYMLINK_DISABLE); - kcfg->skc_announce_quota = smb_config_getyorn(SMB_CI_ANNONCE_QUOTA); - kcfg->skc_announce_quota = smb_config_getyorn(SMB_CI_ANNONCE_QUOTA); - + !smb_config_getbool(SMB_CI_DIRSYMLINK_DISABLE); + kcfg->skc_announce_quota = smb_config_getbool(SMB_CI_ANNONCE_QUOTA); kcfg->skc_secmode = smb_config_get_secmode(); - kcfg->skc_lmlevel = smb_config_getnum(SMB_CI_LM_LEVEL); - kcfg->skc_maxconnections = smb_config_getnum(SMB_CI_MAX_CONNECTIONS); - - (void) strlcpy(kcfg->skc_resource_domain, - smb_config_getstr(SMB_CI_DOMAIN_NAME), + (void) smb_getdomainname(kcfg->skc_resource_domain, sizeof (kcfg->skc_resource_domain)); - - (void) smb_gethostname(kcfg->skc_hostname, - sizeof (kcfg->skc_hostname), 1); - - (void) strlcpy(kcfg->skc_system_comment, - smb_config_getstr(SMB_CI_SYS_CMNT), + (void) smb_gethostname(kcfg->skc_hostname, sizeof (kcfg->skc_hostname), + 1); + (void) smb_config_getstr(SMB_CI_SYS_CMNT, kcfg->skc_system_comment, sizeof (kcfg->skc_system_comment)); - - smb_config_unlock(); } /* @@ -304,74 +222,200 @@ smb_gethostname(char *buf, size_t buflen, int upcase) } /* - * The ADS domain is often the same as the DNS domain but they can be - * different - one might be a sub-domain of the other. - * - * If an ADS domain name has been configured, return it. Otherwise, - * return the DNS domain name. - * - * If getdomainname fails, the returned buffer will contain an empty - * string. + * Obtain the fully-qualified name for this machine. If the + * hostname is fully-qualified, accept it. Otherwise, try to + * find an appropriate domain name to append to the hostname. */ int -smb_getdomainname(char *buf, size_t buflen) +smb_getfqhostname(char *buf, size_t buflen) { - char *domain; + char hostname[MAXHOSTNAMELEN]; + char domain[MAXHOSTNAMELEN]; - if (buf == NULL || buflen == 0) + hostname[0] = '\0'; + domain[0] = '\0'; + + if (smb_gethostname(hostname, MAXHOSTNAMELEN, 0) != 0) return (-1); - smb_config_rdlock(); + if (smb_getfqdomainname(domain, MAXHOSTNAMELEN) != 0) + return (-1); + + if (hostname[0] == '\0') + return (-1); - domain = smb_config_getstr(SMB_CI_ADS_DOMAIN); - if ((domain != NULL) && (*domain != '\0')) { - (void) strlcpy(buf, domain, buflen); - smb_config_unlock(); + if (domain[0] == '\0') { + (void) strlcpy(buf, hostname, buflen); return (0); } - smb_config_unlock(); + (void) snprintf(buf, buflen, "%s.%s", hostname, domain); + return (0); +} - if (getdomainname(buf, buflen) != 0) { - *buf = '\0'; +/* + * smb_resolve_netbiosname + * + * Convert the fully-qualified domain name (i.e. fqdn) to a NETBIOS name. + * Upon success, the NETBIOS name will be returned via buf parameter. + * Returns 0 upon success. Otherwise, returns -1. + */ +int +smb_resolve_netbiosname(char *fqdn, char *buf, size_t buflen) +{ + char *p; + + if (!buf) return (-1); - } + + *buf = '\0'; + if (!fqdn) + return (-1); + + (void) strlcpy(buf, fqdn, buflen); + if ((p = strchr(buf, '.')) != NULL) + *p = 0; + + if (strlen(buf) >= NETBIOS_NAME_SZ) + buf[NETBIOS_NAME_SZ - 1] = '\0'; return (0); } /* - * Obtain the fully-qualified name for this machine. If the - * hostname is fully-qualified, accept it. Otherwise, try to - * find an appropriate domain name to append to the hostname. + * smb_getdomainname + * + * Returns NETBIOS name of the domain if the system is in domain + * mode. Or returns workgroup name if the system is in workgroup + * mode. */ int -smb_getfqhostname(char *buf, size_t buflen) +smb_getdomainname(char *buf, size_t buflen) { - char hostname[MAXHOSTNAMELEN]; char domain[MAXHOSTNAMELEN]; + int rc; - hostname[0] = '\0'; - domain[0] = '\0'; + if (buf == NULL || buflen == 0) + return (-1); - if (smb_gethostname(hostname, MAXHOSTNAMELEN, 0) != 0) + *buf = '\0'; + rc = smb_config_getstr(SMB_CI_DOMAIN_NAME, domain, + sizeof (domain)); + + if ((rc != SMBD_SMF_OK) || (*domain == '\0')) return (-1); - if (smb_getdomainname(domain, MAXHOSTNAMELEN) != 0) + (void) smb_resolve_netbiosname(domain, buf, buflen); + return (0); +} + +/* + * smb_resolve_fqdn + * + * Converts the NETBIOS name of the domain (i.e. nbt_domain) to a fully + * qualified domain name. The domain from either the domain field or + * search list field of the /etc/resolv.conf will be returned via the + * buf parameter if the first label of the domain matches the given + * NETBIOS name. + * + * Returns -1 upon error. If a match is found, returns 1. Otherwise, + * returns 0. + */ +int +smb_resolve_fqdn(char *nbt_domain, char *buf, size_t buflen) +{ + struct __res_state res_state; + int i, found = 0; + char *p; + int dlen; + + if (!buf) return (-1); - if (hostname[0] == '\0') + *buf = '\0'; + if (!nbt_domain) return (-1); - if (domain[0] == '\0') { - (void) strlcpy(buf, hostname, buflen); - return (0); + bzero(&res_state, sizeof (struct __res_state)); + if (res_ninit(&res_state)) + return (-1); + + if (*nbt_domain == '\0') { + if (*res_state.defdname == '\0') { + res_ndestroy(&res_state); + return (0); + } + + (void) strlcpy(buf, res_state.defdname, buflen); + res_ndestroy(&res_state); + return (1); } - (void) snprintf(buf, buflen, "%s.%s", hostname, domain); - return (0); + dlen = strlen(nbt_domain); + if (!strncasecmp(nbt_domain, res_state.defdname, dlen)) { + (void) strlcpy(buf, res_state.defdname, buflen); + res_ndestroy(&res_state); + return (1); + } + + for (i = 0; (p = res_state.dnsrch[i]) != NULL; i++) { + if (!strncasecmp(nbt_domain, p, dlen)) { + (void) strlcpy(buf, p, buflen); + found = 1; + break; + } + + } + + res_ndestroy(&res_state); + return (found); +} + +/* + * smb_getfqdomainname + * + * If the domain_name property value is FQDN, it will be returned. + * In domain mode, the domain from either the domain field or + * search list field of the /etc/resolv.conf will be returned via the + * buf parameter if the first label of the domain matches the + * domain_name property. In workgroup mode, it returns the local + * domain. + * + * Returns 0 upon success. Otherwise, returns -1. + */ +int +smb_getfqdomainname(char *buf, size_t buflen) +{ + char domain[MAXHOSTNAMELEN]; + int rc = 0; + + if (buf == NULL || buflen == 0) + return (-1); + + *buf = '\0'; + if (smb_config_get_secmode() == SMB_SECMODE_DOMAIN) { + rc = smb_config_getstr(SMB_CI_DOMAIN_NAME, domain, + sizeof (domain)); + + if ((rc != SMBD_SMF_OK) || (*domain == '\0')) + return (-1); + + if (strchr(domain, '.') == NULL) { + if (smb_resolve_fqdn(domain, buf, buflen) != 1) + rc = -1; + } else { + (void) strlcpy(buf, domain, buflen); + } + } else { + if (smb_resolve_fqdn("", buf, buflen) != 1) + rc = -1; + } + + return (rc); } + + /* * Temporary fbt for dtrace until user space sdt enabled. */ diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_lgrp.c b/usr/src/lib/smbsrv/libsmb/common/smb_lgrp.c new file mode 100644 index 0000000000..934b804dcd --- /dev/null +++ b/usr/src/lib/smbsrv/libsmb/common/smb_lgrp.c @@ -0,0 +1,2319 @@ +/* + * 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 2008 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <stdlib.h> +#include <strings.h> +#include <unistd.h> +#include <syslog.h> +#include <thread.h> +#include <synch.h> +#include <grp.h> +#include <assert.h> +#include <libintl.h> +#include <smbsrv/libsmb.h> + +#define SMB_LGRP_LOCAL_IDX 0 +#define SMB_LGRP_BUILTIN_IDX 1 + +#define SMB_LGRP_DB_NAME "/var/smb/smbgroup.db" +#define SMB_LGRP_DB_TIMEOUT 3000 /* in millisecond */ +#define SMB_LGRP_DB_VERMAJOR 1 +#define SMB_LGRP_DB_VERMINOR 0 +#define SMB_LGRP_DB_MAGIC 0x4C475250 /* LGRP */ + +#define SMB_LGRP_DB_ORD 1 /* open read-only */ +#define SMB_LGRP_DB_ORW 2 /* open read/write */ + +#define SMB_LGRP_DB_ADDMEMBER 1 +#define SMB_LGRP_DB_DELMEMBER 2 + +/* + * members column of the groups table is an array of + * member structure smb_lgmid_t defined below. + * + * privs column of the groups table is an array of bytes + * where each byte is the id of an enable privilege + */ +#define SMB_LGRP_DB_SQL \ + "CREATE TABLE db_info (" \ + " ver_major INTEGER," \ + " ver_minor INTEGER," \ + " magic INTEGER" \ + ");" \ + "" \ + "CREATE TABLE domains (" \ + " dom_idx INTEGER PRIMARY KEY," \ + " dom_sid TEXT UNIQUE," \ + " dom_cnt INTEGER" \ + ");" \ + "" \ + "CREATE UNIQUE INDEX domsid_idx ON domains (dom_sid);" \ + "" \ + "CREATE TABLE groups (" \ + " name TEXT PRIMARY KEY," \ + " sid_idx INTEGER," \ + " sid_rid INTEGER," \ + " sid_type INTEGER," \ + " sid_attrs INTEGER," \ + " comment TEXT," \ + " n_privs INTEGER," \ + " privs BLOB," \ + " n_members INTEGER," \ + " members BLOB" \ + ");" \ + "" \ + "CREATE INDEX grprid_idx ON groups (sid_rid);" + +/* + * Number of groups table columns + */ +#define SMB_LGRP_GTBL_NCOL 10 + +#define SMB_LGRP_GTBL_NAME 0 +#define SMB_LGRP_GTBL_SIDIDX 1 +#define SMB_LGRP_GTBL_SIDRID 2 +#define SMB_LGRP_GTBL_SIDTYP 3 +#define SMB_LGRP_GTBL_SIDATR 4 +#define SMB_LGRP_GTBL_CMNT 5 +#define SMB_LGRP_GTBL_NPRIVS 6 +#define SMB_LGRP_GTBL_PRIVS 7 +#define SMB_LGRP_GTBL_NMEMBS 8 +#define SMB_LGRP_GTBL_MEMBS 9 + +#define SMB_LGRP_INFO_NONE 0x00 +#define SMB_LGRP_INFO_NAME 0x01 +#define SMB_LGRP_INFO_CMNT 0x02 +#define SMB_LGRP_INFO_SID 0x04 +#define SMB_LGRP_INFO_PRIV 0x08 +#define SMB_LGRP_INFO_MEMB 0x10 +#define SMB_LGRP_INFO_ALL 0x1F + +#define NULL_MSGCHK(msg) ((msg) ? (msg) : "NULL") + +/* Member ID */ +typedef struct smb_lgmid { + uint32_t m_idx; + uint32_t m_rid; + uint16_t m_type; +} smb_lgmid_t; + +#define SMB_LGRP_MID_HEXSZ 32 + +/* Member list */ +typedef struct smb_lgmlist { + uint32_t m_cnt; + char *m_ids; +} smb_lgmlist_t; + +/* Privilege ID */ +typedef uint8_t smb_lgpid_t; + +/* Privilege list */ +typedef struct smb_lgplist { + uint32_t p_cnt; + smb_lgpid_t *p_ids; +} smb_lgplist_t; + +static mutex_t smb_lgrp_lsid_mtx; +static nt_sid_t *smb_lgrp_lsid; + +static int smb_lgrp_db_init(void); +static sqlite *smb_lgrp_db_open(int); +static void smb_lgrp_db_close(sqlite *); +static int smb_lgrp_db_setinfo(sqlite *); + +static boolean_t smb_lgrp_gtbl_exists(sqlite *, char *); +static int smb_lgrp_gtbl_lookup(sqlite *, int, smb_group_t *, int, ...); +static int smb_lgrp_gtbl_insert(sqlite *, smb_group_t *); +static int smb_lgrp_gtbl_update(sqlite *, char *, smb_group_t *, int); +static int smb_lgrp_gtbl_delete(sqlite *, char *); +static int smb_lgrp_gtbl_update_mlist(sqlite *, char *, smb_gsid_t *, int); +static int smb_lgrp_gtbl_update_plist(sqlite *, char *, uint8_t, boolean_t); +static int smb_lgrp_gtbl_count(sqlite *, int, int *); + +static int smb_lgrp_dtbl_insert(sqlite *, char *, uint32_t *); +static int smb_lgrp_dtbl_getidx(sqlite *, nt_sid_t *, uint16_t, + uint32_t *, uint32_t *); +static int smb_lgrp_dtbl_getsid(sqlite *, uint32_t, nt_sid_t **); + +static int smb_lgrp_mlist_add(smb_lgmlist_t *, smb_lgmid_t *, smb_lgmlist_t *); +static int smb_lgrp_mlist_del(smb_lgmlist_t *, smb_lgmid_t *, smb_lgmlist_t *); + +static int smb_lgrp_plist_add(smb_lgplist_t *, smb_lgpid_t, smb_lgplist_t *); +static int smb_lgrp_plist_del(smb_lgplist_t *, smb_lgpid_t, smb_lgplist_t *); + +static void smb_lgrp_encode_privset(smb_group_t *, smb_lgplist_t *); + +static int smb_lgrp_decode(smb_group_t *, char **, int, sqlite *); +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_chkmember(uint16_t); +static int smb_lgrp_getsid(int, uint32_t *, uint16_t, sqlite *, nt_sid_t **); + +#ifdef _LP64 +/* + * We cannot make 64-bit version of libsqlite because the code + * has some problems. + */ + +/*ARGSUSED*/ +sqlite * +sqlite_open(const char *filename, int mode, char **errmsg) +{ + return (NULL); +} + +/*ARGSUSED*/ +void +sqlite_close(sqlite *db) +{ +} + +/*ARGSUSED*/ +char * +sqlite_mprintf(const char *fmt, ...) +{ + return (NULL); +} + +/*ARGSUSED*/ +void +sqlite_freemem(void *p) +{ +} + +/*ARGSUSED*/ +int +sqlite_compile(sqlite *db, const char *zSql, const char **pzTail, + sqlite_vm **ppVm, char **pzErrmsg) +{ + return (SQLITE_ERROR); +} + +/*ARGSUSED*/ +void +sqlite_free_table(char **res) +{ +} + +/*ARGSUSED*/ +int +sqlite_last_insert_rowid(sqlite *db) +{ + return (-1); +} + +/*ARGSUSED*/ +void +sqlite_busy_timeout(sqlite *db, int ms) +{ +} + +/*ARGSUSED*/ +int +sqlite_get_table(sqlite *db, const char *zSql, char ***pazResult, int *pnRow, + int *pnColumn, char **pzErrMsg) +{ + return (SQLITE_ERROR); +} + +/*ARGSUSED*/ +int +sqlite_step(sqlite_vm *pVm, int *pN, const char ***pazValue, + const char ***pazColName) +{ + return (SQLITE_ERROR); +} + +/*ARGSUSED*/ +int +sqlite_exec(sqlite *db, const char *zSql, sqlite_callback xCallback, void *pArg, + char **pzErrMsg) +{ + return (SQLITE_ERROR); +} + +/*ARGSUSED*/ +int +sqlite_finalize(sqlite_vm *pVm, char **pzErrMsg) +{ + return (SQLITE_ERROR); +} +#endif /* _LP64 */ + +/* + * smb_lgrp_add + * + * Create a local group with the given name and comment. + * This new group doesn't have any members and no enabled + * privileges. + * + * No well-known accounts can be added other than Administators, + * Backup Operators and Power Users. These built-in groups + * won't have any members when created but a set of default + * privileges will be enabled for them. + */ +int +smb_lgrp_add(char *gname, char *cmnt) +{ + well_known_account_t *wk_acct; + struct group *pxgrp; + smb_group_t grp; + nt_sid_t *sid = NULL; + sqlite *db; + int rc; + + (void) trim_whitespace(gname); + if (!smb_lgrp_chkname(gname)) + return (SMB_LGRP_INVALID_NAME); + + if (cmnt && (strlen(cmnt) > SMB_LGRP_COMMENT_MAX)) + return (SMB_LGRP_INVALID_ARG); + + bzero(&grp, sizeof (grp)); + grp.sg_name = utf8_strlwr(gname); + grp.sg_cmnt = cmnt; + + wk_acct = nt_builtin_lookup(gname); + if (wk_acct == NULL) { + if ((pxgrp = getgrnam(gname)) == NULL) + return (SMB_LGRP_NOT_FOUND); + + /* + * Make sure a local SID can be obtained + */ + if (smb_idmap_getsid(pxgrp->gr_gid, SMB_IDMAP_GROUP, &sid) + != IDMAP_SUCCESS) + return (SMB_LGRP_NO_SID); + + if (!nt_sid_is_indomain(smb_lgrp_lsid, sid)) { + free(sid); + return (SMB_LGRP_SID_NOTLOCAL); + } + + grp.sg_id.gs_type = SidTypeAlias; + grp.sg_domain = SMB_LGRP_LOCAL; + grp.sg_rid = pxgrp->gr_gid; + } else { + if (wk_acct->flags & LGF_HIDDEN) { + /* cannot add well-known accounts */ + return (SMB_LGRP_WKSID); + } + + grp.sg_id.gs_type = wk_acct->sid_name_use; + if ((sid = nt_sid_strtosid(wk_acct->sid)) == NULL) + return (SMB_LGRP_NO_MEMORY); + (void) nt_sid_get_rid(sid, &grp.sg_rid); + free(sid); + grp.sg_domain = SMB_LGRP_BUILTIN; + + grp.sg_privs = smb_privset_new(); + smb_lgrp_set_default_privs(&grp); + } + + + grp.sg_attr = SE_GROUP_MANDATORY | SE_GROUP_ENABLED_BY_DEFAULT | + SE_GROUP_ENABLED; + + db = smb_lgrp_db_open(SMB_LGRP_DB_ORW); + rc = smb_lgrp_gtbl_insert(db, &grp); + smb_lgrp_db_close(db); + + smb_privset_free(grp.sg_privs); + return (rc); +} + +/* + * smb_lgrp_rename + * + * Renames the given group + */ +int +smb_lgrp_rename(char *gname, char *new_gname) +{ + smb_group_t grp; + sqlite *db; + int rc; + + (void) trim_whitespace(gname); + if (!smb_lgrp_chkname(gname)) + return (SMB_LGRP_INVALID_NAME); + + (void) trim_whitespace(new_gname); + if (!smb_lgrp_chkname(gname)) + return (SMB_LGRP_INVALID_NAME); + + if (utf8_strcasecmp(gname, new_gname) == 0) + return (SMB_LGRP_SUCCESS); + + /* Cannot rename well-known groups */ + if (nt_builtin_is_wellknown(gname)) + return (SMB_LGRP_WKSID); + + /* Cannot rename to a well-known groups */ + if (nt_builtin_is_wellknown(new_gname)) + return (SMB_LGRP_WKSID); + + grp.sg_name = new_gname; + + db = smb_lgrp_db_open(SMB_LGRP_DB_ORW); + rc = smb_lgrp_gtbl_update(db, gname, &grp, SMB_LGRP_GTBL_NAME); + smb_lgrp_db_close(db); + + return (rc); +} + +/* + * smb_lgrp_delete + * + * Deletes the specified local group. + */ +int +smb_lgrp_delete(char *gname) +{ + sqlite *db; + int rc; + + (void) trim_whitespace(gname); + if (!smb_lgrp_chkname(gname)) + return (SMB_LGRP_INVALID_NAME); + + /* Cannot remove a built-in group */ + if (nt_builtin_is_wellknown(gname)) + return (SMB_LGRP_WKSID); + + db = smb_lgrp_db_open(SMB_LGRP_DB_ORW); + rc = smb_lgrp_gtbl_delete(db, gname); + smb_lgrp_db_close(db); + + return (rc); +} + +/* + * smb_lgrp_setcmnt + * + * Sets the description for the given group + */ +int +smb_lgrp_setcmnt(char *gname, char *cmnt) +{ + smb_group_t grp; + sqlite *db; + int rc; + + (void) trim_whitespace(gname); + if (!smb_lgrp_chkname(gname)) + return (SMB_LGRP_INVALID_NAME); + + if (cmnt && (strlen(cmnt) > SMB_LGRP_COMMENT_MAX)) + return (SMB_LGRP_INVALID_ARG); + + grp.sg_cmnt = cmnt; + + db = smb_lgrp_db_open(SMB_LGRP_DB_ORW); + rc = smb_lgrp_gtbl_update(db, gname, &grp, SMB_LGRP_GTBL_CMNT); + smb_lgrp_db_close(db); + + return (rc); +} + +/* + * smb_lgrp_getcmnt + * + * Obtain the description of the specified group + */ +int +smb_lgrp_getcmnt(char *gname, char **cmnt) +{ + smb_group_t grp; + sqlite *db; + int rc; + + (void) trim_whitespace(gname); + if (!smb_lgrp_chkname(gname)) + return (SMB_LGRP_INVALID_NAME); + + if (cmnt == NULL) + return (SMB_LGRP_INVALID_ARG); + + db = smb_lgrp_db_open(SMB_LGRP_DB_ORD); + rc = smb_lgrp_gtbl_lookup(db, SMB_LGRP_GTBL_NAME, &grp, + SMB_LGRP_INFO_CMNT, gname); + smb_lgrp_db_close(db); + + if (rc == SMB_LGRP_SUCCESS) { + *cmnt = grp.sg_cmnt; + grp.sg_cmnt = NULL; + smb_lgrp_free(&grp); + } + + return (rc); +} + + +/* + * smb_lgrp_setpriv + * + * Enable/disable the specified privilge for the group + */ +int +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)) + return (SMB_LGRP_INVALID_NAME); + + if ((priv_lid < SE_MIN_LUID) || (priv_lid > SE_MAX_LUID)) + return (SMB_LGRP_NO_SUCH_PRIV); + + db = smb_lgrp_db_open(SMB_LGRP_DB_ORW); + rc = smb_lgrp_gtbl_update_plist(db, gname, priv_lid, enable); + smb_lgrp_db_close(db); + + if (enable) { + if (rc == SMB_LGRP_PRIV_HELD) + rc = SMB_LGRP_SUCCESS; + } else { + if (rc == SMB_LGRP_PRIV_NOT_HELD) + rc = SMB_LGRP_SUCCESS; + } + + return (rc); +} + +/* + * smb_lgrp_getpriv + * + * Obtain the status of the specified privilge for the group + */ +int +smb_lgrp_getpriv(char *gname, uint8_t priv_lid, boolean_t *enable) +{ + sqlite *db; + smb_group_t grp; + int rc; + + (void) trim_whitespace(gname); + if (!smb_lgrp_chkname(gname)) + return (SMB_LGRP_INVALID_NAME); + + if ((priv_lid < SE_MIN_LUID) || (priv_lid > SE_MAX_LUID)) + return (SMB_LGRP_NO_SUCH_PRIV); + + db = smb_lgrp_db_open(SMB_LGRP_DB_ORD); + rc = smb_lgrp_gtbl_lookup(db, SMB_LGRP_GTBL_NAME, &grp, + SMB_LGRP_INFO_PRIV, gname); + smb_lgrp_db_close(db); + + if (rc == SMB_LGRP_SUCCESS) { + *enable = (smb_privset_query(grp.sg_privs, priv_lid) == 1); + smb_lgrp_free(&grp); + } + + return (rc); +} + +/* + * smb_lgrp_add_member + * + * Add the given account to the specified group as its member. + */ +int +smb_lgrp_add_member(char *gname, nt_sid_t *msid, uint16_t sid_type) +{ + sqlite *db; + smb_gsid_t mid; + int rc; + + (void) trim_whitespace(gname); + if (!smb_lgrp_chkname(gname)) + return (SMB_LGRP_INVALID_NAME); + + if (!nt_sid_is_valid(msid)) + return (SMB_LGRP_INVALID_ARG); + + if (!smb_lgrp_chkmember(sid_type)) + return (SMB_LGRP_INVALID_MEMBER); + + mid.gs_sid = msid; + mid.gs_type = sid_type; + + db = smb_lgrp_db_open(SMB_LGRP_DB_ORW); + rc = smb_lgrp_gtbl_update_mlist(db, gname, &mid, SMB_LGRP_DB_ADDMEMBER); + smb_lgrp_db_close(db); + + return (rc); +} + +/* + * smb_lgrp_del_member + * + * Delete the specified member from the given group. + */ +int +smb_lgrp_del_member(char *gname, nt_sid_t *msid, uint16_t sid_type) +{ + sqlite *db; + smb_gsid_t mid; + int rc; + + (void) trim_whitespace(gname); + if (!smb_lgrp_chkname(gname)) + return (SMB_LGRP_INVALID_NAME); + + if (!nt_sid_is_valid(msid)) + return (SMB_LGRP_INVALID_ARG); + + mid.gs_sid = msid; + mid.gs_type = sid_type; + + db = smb_lgrp_db_open(SMB_LGRP_DB_ORW); + rc = smb_lgrp_gtbl_update_mlist(db, gname, &mid, SMB_LGRP_DB_DELMEMBER); + smb_lgrp_db_close(db); + + return (rc); +} + +/* + * smb_lgrp_getbyname + * + * Retrieves the information of the group specified by + * the given name. + * + * Note that this function doesn't allocate the group + * structure itself only the fields, so the given grp + * pointer has to point to a group structure. + * Caller must free the allocated memories for the fields + * by calling smb_lgrp_free(). + */ +int +smb_lgrp_getbyname(char *gname, smb_group_t *grp) +{ + sqlite *db; + int rc; + + (void) trim_whitespace(gname); + if (!smb_lgrp_chkname(gname)) + return (SMB_LGRP_INVALID_NAME); + + db = smb_lgrp_db_open(SMB_LGRP_DB_ORD); + rc = smb_lgrp_gtbl_lookup(db, SMB_LGRP_GTBL_NAME, grp, + SMB_LGRP_INFO_ALL, gname); + smb_lgrp_db_close(db); + + return (rc); +} + +/* + * smb_lgrp_getbyrid + * + * Retrieves the information of the group specified by + * the given RID and domain type. + * + * Note that this function doesn't allocate the group + * structure itself only the fields, so the given grp + * pointer has to point to a group structure. + * Caller must free the allocated memories for the fields + * by calling smb_lgrp_free(). + * + * If grp is NULL no information would be returned. The + * return value of SMB_LGRP_SUCCESS will indicate that a + * group with the given information exists. + */ +int +smb_lgrp_getbyrid(uint32_t rid, smb_gdomain_t domtype, smb_group_t *grp) +{ + smb_group_t tmpgrp; + sqlite *db; + int infolvl = SMB_LGRP_INFO_ALL; + int rc; + + if (grp == NULL) { + grp = &tmpgrp; + infolvl = SMB_LGRP_INFO_NONE; + } + + db = smb_lgrp_db_open(SMB_LGRP_DB_ORD); + rc = smb_lgrp_gtbl_lookup(db, SMB_LGRP_GTBL_SIDRID, grp, infolvl, + rid, domtype); + smb_lgrp_db_close(db); + + return (rc); +} + +/* + * smb_lgrp_numbydomain + * + * Returns the number of groups in the given domain in the + * arg 'count' + */ +int +smb_lgrp_numbydomain(smb_gdomain_t dom_type, int *count) +{ + sqlite *db; + int dom_idx; + int rc; + + switch (dom_type) { + case SMB_LGRP_LOCAL: + dom_idx = SMB_LGRP_LOCAL_IDX; + break; + case SMB_LGRP_BUILTIN: + dom_idx = SMB_LGRP_BUILTIN_IDX; + break; + default: + *count = 0; + return (SMB_LGRP_INVALID_ARG); + } + + db = smb_lgrp_db_open(SMB_LGRP_DB_ORD); + rc = smb_lgrp_gtbl_count(db, dom_idx, count); + smb_lgrp_db_close(db); + + return (rc); +} + +/* + * smb_lgrp_numbydomain + * + * Returns the number of groups which have the given SID + * as a member. + */ +int +smb_lgrp_numbymember(nt_sid_t *msid, int *count) +{ + smb_giter_t gi; + smb_group_t grp; + int rc; + + *count = 0; + rc = smb_lgrp_iteropen(&gi); + if (rc != SMB_LGRP_SUCCESS) + return (rc); + + while (smb_lgrp_iterate(&gi, &grp) == SMB_LGRP_SUCCESS) { + if (smb_lgrp_is_member(&grp, msid)) + (*count)++; + smb_lgrp_free(&grp); + } + smb_lgrp_iterclose(&gi); + return (SMB_LGRP_SUCCESS); +} + +/* + * smb_lgrp_free + * + * Frees the allocated memory for the fields of the given + * group structure. Note that this function doesn't free + * the group itself. + */ +void +smb_lgrp_free(smb_group_t *grp) +{ + int i; + + if (grp == NULL) + return; + + free(grp->sg_name); + free(grp->sg_cmnt); + free(grp->sg_id.gs_sid); + smb_privset_free(grp->sg_privs); + + for (i = 0; i < grp->sg_nmembers; i++) + free(grp->sg_members[i].gs_sid); + free(grp->sg_members); +} + +/* + * smb_lgrp_iteropen + * + * Initializes the given group iterator by opening + * the group database and creating a virtual machine + * for iteration. + */ +int +smb_lgrp_iteropen(smb_giter_t *iter) +{ + char *sql; + char *errmsg = NULL; + int rc = SMB_LGRP_SUCCESS; + + assert(iter); + + bzero(iter, sizeof (smb_giter_t)); + + sql = sqlite_mprintf("SELECT * FROM groups"); + if (sql == NULL) + return (SMB_LGRP_NO_MEMORY); + + iter->sgi_db = smb_lgrp_db_open(SMB_LGRP_DB_ORD); + if (iter->sgi_db == NULL) { + sqlite_freemem(sql); + return (SMB_LGRP_DBOPEN_FAILED); + } + + rc = sqlite_compile(iter->sgi_db, sql, NULL, &iter->sgi_vm, &errmsg); + sqlite_freemem(sql); + + if (rc != SQLITE_OK) { + syslog(LOG_DEBUG, "failed to create a VM (%s)", + NULL_MSGCHK(errmsg)); + rc = SMB_LGRP_DB_ERROR; + } + + return (rc); +} + +/* + * smb_lgrp_iterclose + * + * Closes the given group iterator. + */ +void +smb_lgrp_iterclose(smb_giter_t *iter) +{ + char *errmsg = NULL; + int rc; + + assert(iter); + + rc = sqlite_finalize(iter->sgi_vm, &errmsg); + if (rc != SQLITE_OK) { + syslog(LOG_DEBUG, "failed to destroy a VM (%s)", + NULL_MSGCHK(errmsg)); + } + + smb_lgrp_db_close(iter->sgi_db); +} + +/* + * smb_lgrp_iterate + * + * Iterate through group database + * Group information is returned in provided group structure. + * + * Note that this function doesn't allocate the group + * structure itself only the fields, so the given grp + * pointer has to point to a group structure. + * Caller must free the allocated memories for the fields + * by calling smb_lgrp_free(). + */ +int +smb_lgrp_iterate(smb_giter_t *iter, smb_group_t *grp) +{ + const char **values; + int ncol; + int rc; + int i; + + if (iter->sgi_vm == NULL || iter->sgi_db == NULL) + return (SMB_LGRP_INVALID_ARG); + + bzero(grp, sizeof (smb_group_t)); + rc = sqlite_step(iter->sgi_vm, &ncol, &values, NULL); + if (rc == SQLITE_DONE) + return (SMB_LGRP_NO_MORE); + + if (rc != SQLITE_ROW) + return (SMB_LGRP_DBEXEC_FAILED); + + if (ncol != SMB_LGRP_GTBL_NCOL) + return (SMB_LGRP_DB_ERROR); + + for (i = 0; i < ncol; i++) { + if (values[i] == NULL) + return (SMB_LGRP_DB_ERROR); + } + + return (smb_lgrp_decode(grp, (char **)values, SMB_LGRP_INFO_ALL, + iter->sgi_db)); +} + +/* + * smb_lgrp_is_member + * + * Check to see if the specified account is a member of + * the given group. + */ +boolean_t +smb_lgrp_is_member(smb_group_t *grp, nt_sid_t *sid) +{ + int i; + + if (grp == NULL || grp->sg_members == NULL || sid == NULL) + return (B_FALSE); + + for (i = 0; i < grp->sg_nmembers; i++) { + if (nt_sid_is_equal(grp->sg_members[i].gs_sid, sid)) + return (B_TRUE); + } + + return (B_FALSE); +} + +/* + * smb_lgrp_strerror + * + * Returns a text for the given group error code. + */ +char * +smb_lgrp_strerror(int errno) +{ + switch (errno) { + case SMB_LGRP_SUCCESS: + return (dgettext(TEXT_DOMAIN, "success")); + case SMB_LGRP_INVALID_ARG: + return (dgettext(TEXT_DOMAIN, "invalid argument")); + case SMB_LGRP_INVALID_MEMBER: + return (dgettext(TEXT_DOMAIN, "invalid member type")); + case SMB_LGRP_INVALID_NAME: + return (dgettext(TEXT_DOMAIN, "invalid name")); + case SMB_LGRP_NOT_FOUND: + return (dgettext(TEXT_DOMAIN, "group not found")); + case SMB_LGRP_EXISTS: + return (dgettext(TEXT_DOMAIN, "group exists")); + case SMB_LGRP_NO_SID: + return (dgettext(TEXT_DOMAIN, "cannot obtain a SID")); + case SMB_LGRP_NO_LOCAL_SID: + return (dgettext(TEXT_DOMAIN, "cannot get the machine SID")); + case SMB_LGRP_SID_NOTLOCAL: + return (dgettext(TEXT_DOMAIN, "not a local SID")); + case SMB_LGRP_WKSID: + return (dgettext(TEXT_DOMAIN, + "operation not permitted on well-known accounts")); + case SMB_LGRP_NO_MEMORY: + return (dgettext(TEXT_DOMAIN, "not enough memory")); + case SMB_LGRP_DB_ERROR: + return (dgettext(TEXT_DOMAIN, "database operation error")); + case SMB_LGRP_DBINIT_ERROR: + return (dgettext(TEXT_DOMAIN, "database initialization error")); + case SMB_LGRP_INTERNAL_ERROR: + return (dgettext(TEXT_DOMAIN, "internal error")); + case SMB_LGRP_MEMBER_IN_GROUP: + return (dgettext(TEXT_DOMAIN, "member already in the group")); + case SMB_LGRP_MEMBER_NOT_IN_GROUP: + return (dgettext(TEXT_DOMAIN, "not a member")); + case SMB_LGRP_NO_SUCH_PRIV: + return (dgettext(TEXT_DOMAIN, "no such privilege")); + case SMB_LGRP_NO_SUCH_DOMAIN: + return (dgettext(TEXT_DOMAIN, "no such domain SID")); + case SMB_LGRP_PRIV_HELD: + return (dgettext(TEXT_DOMAIN, "already holds the privilege")); + case SMB_LGRP_PRIV_NOT_HELD: + return (dgettext(TEXT_DOMAIN, "privilege not held")); + case SMB_LGRP_BAD_DATA: + return (dgettext(TEXT_DOMAIN, "bad data")); + case SMB_LGRP_NO_MORE: + return (dgettext(TEXT_DOMAIN, "no more groups")); + case SMB_LGRP_DBOPEN_FAILED: + return (dgettext(TEXT_DOMAIN, "failed openning database")); + case SMB_LGRP_DBEXEC_FAILED: + return (dgettext(TEXT_DOMAIN, + "failed executing database operation")); + case SMB_LGRP_DBINIT_FAILED: + return (dgettext(TEXT_DOMAIN, "failed initializing database")); + case SMB_LGRP_DOMLKP_FAILED: + return (dgettext(TEXT_DOMAIN, "failed getting the domain SID")); + case SMB_LGRP_DOMINS_FAILED: + return (dgettext(TEXT_DOMAIN, + "failed inserting the domain SID")); + case SMB_LGRP_INSERT_FAILED: + return (dgettext(TEXT_DOMAIN, "failed inserting the group")); + case SMB_LGRP_DELETE_FAILED: + return (dgettext(TEXT_DOMAIN, "failed deleting the group")); + case SMB_LGRP_UPDATE_FAILED: + return (dgettext(TEXT_DOMAIN, "failed updating the group")); + case SMB_LGRP_LOOKUP_FAILED: + return (dgettext(TEXT_DOMAIN, "failed looking up the group")); + } + + return (dgettext(TEXT_DOMAIN, "unknown error code")); +} + +/* + * smb_lgrp_chkmember + * + * Determines valid account types for being member of + * a local group. + * + * Currently, we just support users as valid members. + */ +static boolean_t +smb_lgrp_chkmember(uint16_t sid_type) +{ + return (sid_type == SidTypeUser); +} + +/* + * smb_lgrp_start + * + * Initializes the library private global variables. + * If the database doesn't exist, it'll create it and adds the + * predefined builtin groups. + */ +int +smb_lgrp_start(void) +{ + char *supported_bg[] = + {"Administrators", "Backup Operators", "Power Users"}; + well_known_account_t *wka; + int rc, i, ngrp; + char *lsid_str; + + (void) mutex_init(&smb_lgrp_lsid_mtx, USYNC_THREAD, NULL); + (void) mutex_lock(&smb_lgrp_lsid_mtx); + lsid_str = smb_config_get_localsid(); + if (lsid_str == NULL) { + (void) mutex_unlock(&smb_lgrp_lsid_mtx); + return (SMB_LGRP_NO_LOCAL_SID); + } + + smb_lgrp_lsid = nt_sid_strtosid(lsid_str); + free(lsid_str); + if (!nt_sid_is_valid(smb_lgrp_lsid)) { + free(smb_lgrp_lsid); + smb_lgrp_lsid = NULL; + (void) mutex_unlock(&smb_lgrp_lsid_mtx); + return (SMB_LGRP_NO_LOCAL_SID); + } + + rc = smb_lgrp_db_init(); + if (rc != SMB_LGRP_SUCCESS) { + free(smb_lgrp_lsid); + smb_lgrp_lsid = NULL; + (void) mutex_unlock(&smb_lgrp_lsid_mtx); + return (rc); + } + (void) mutex_unlock(&smb_lgrp_lsid_mtx); + + ngrp = sizeof (supported_bg) / sizeof (supported_bg[0]); + for (i = 0; i < ngrp; i++) { + wka = nt_builtin_lookup(supported_bg[i]); + if (wka == NULL) + continue; + rc = smb_lgrp_add(wka->name, wka->desc); + if (rc != SMB_LGRP_SUCCESS) + syslog(LOG_DEBUG, "failed to add %s", wka->name); + } + + return (SMB_LGRP_SUCCESS); +} + +/* + * smb_lgrp_stop + * + * Unintialize the library global private variables. + */ +void +smb_lgrp_stop(void) +{ + (void) mutex_lock(&smb_lgrp_lsid_mtx); + free(smb_lgrp_lsid); + smb_lgrp_lsid = NULL; + (void) mutex_unlock(&smb_lgrp_lsid_mtx); + (void) mutex_destroy(&smb_lgrp_lsid_mtx); +} + +/* + * smb_lgrp_db_open + * + * Opens group database with the given mode. + */ +static sqlite * +smb_lgrp_db_open(int mode) +{ + sqlite *db; + char *errmsg = NULL; + + db = sqlite_open(SMB_LGRP_DB_NAME, mode, &errmsg); + if (db == NULL) { + syslog(LOG_ERR, "failed to open group database (%s)", + NULL_MSGCHK(errmsg)); + sqlite_freemem(errmsg); + } + + return (db); +} + +/* + * smb_lgrp_db_close + * + * Closes the given database handle + */ +static void +smb_lgrp_db_close(sqlite *db) +{ + if (db) { + sqlite_close(db); + } +} + +/* + * smb_lgrp_db_init + * + * Creates the group database based on the defined SQL statement. + * It also initializes db_info and domain tables. + */ +static int +smb_lgrp_db_init(void) +{ + int dbrc = SQLITE_OK; + int rc = SMB_LGRP_SUCCESS; + sqlite *db = NULL; + char *errmsg = NULL; + + db = sqlite_open(SMB_LGRP_DB_NAME, 0600, &errmsg); + if (db == NULL) { + syslog(LOG_ERR, "failed to create group database (%s)", + NULL_MSGCHK(errmsg)); + sqlite_freemem(errmsg); + return (SMB_LGRP_DBOPEN_FAILED); + } + + sqlite_busy_timeout(db, SMB_LGRP_DB_TIMEOUT); + dbrc = sqlite_exec(db, "BEGIN TRANSACTION;", NULL, NULL, &errmsg); + if (dbrc != SQLITE_OK) { + syslog(LOG_DEBUG, "failed to begin database transaction (%s)", + NULL_MSGCHK(errmsg)); + sqlite_freemem(errmsg); + sqlite_close(db); + return (SMB_LGRP_DBEXEC_FAILED); + } + + switch (sqlite_exec(db, SMB_LGRP_DB_SQL, NULL, NULL, &errmsg)) { + case SQLITE_ERROR: + /* + * This is the normal situation: CREATE probably failed because + * tables already exist. It may indicate an error in SQL as well + * but we cannot tell. + */ + sqlite_freemem(errmsg); + dbrc = sqlite_exec(db, "ROLLBACK TRANSACTION", NULL, NULL, + &errmsg); + rc = SMB_LGRP_SUCCESS; + break; + + case SQLITE_OK: + dbrc = sqlite_exec(db, "COMMIT TRANSACTION", NULL, NULL, + &errmsg); + if (dbrc != SQLITE_OK) + break; + rc = smb_lgrp_dtbl_insert(db, NT_BUILTIN_DOMAIN_SIDSTR, + NULL); + if (rc == SMB_LGRP_SUCCESS) + rc = smb_lgrp_db_setinfo(db); + if (rc != SMB_LGRP_SUCCESS) { + (void) sqlite_close(db); + (void) unlink(SMB_LGRP_DB_NAME); + return (rc); + } + break; + + default: + syslog(LOG_ERR, + "failed to initialize group database (%s)", errmsg); + sqlite_freemem(errmsg); + dbrc = sqlite_exec(db, "ROLLBACK TRANSACTION", NULL, NULL, + &errmsg); + rc = SMB_LGRP_DBINIT_FAILED; + break; + } + + if (dbrc != SQLITE_OK) { + /* this is bad - database may be left in a locked state */ + syslog(LOG_DEBUG, "failed to close a transaction (%s)", + NULL_MSGCHK(errmsg)); + sqlite_freemem(errmsg); + } + + (void) sqlite_close(db); + return (rc); +} + +/* + * smb_lgrp_gtbl_lookup + * + * This is a flexible lookup function for the group database. + * The key type can be specified by the 'key' arg and the actual key + * values can be passed after the 'infolvl' arg. 'infolvl' arg specifies + * what information items for the specified group is needed. + * + * Note that the function assumes the given key is unique and only + * specifies one or 0 group. The keys that are supported now are + * the group name and the group SID + * + * Note that this function doesn't allocate the group + * structure itself only the fields, so the given grp + * pointer has to point to a group structure. + * Caller must free the allocated memories for the fields + * by calling smb_lgrp_free(). + */ +static int +smb_lgrp_gtbl_lookup(sqlite *db, int key, smb_group_t *grp, int infolvl, ...) +{ + char *errmsg = NULL; + char *sql; + char **result; + int nrow, ncol; + int rc, dom_idx; + smb_group_t kgrp; + va_list ap; + + if (db == NULL) + return (SMB_LGRP_DBOPEN_FAILED); + + bzero(grp, sizeof (smb_group_t)); + va_start(ap, infolvl); + + switch (key) { + case SMB_LGRP_GTBL_NAME: + kgrp.sg_name = va_arg(ap, char *); + sql = sqlite_mprintf("SELECT * FROM groups WHERE name = '%s'", + kgrp.sg_name); + break; + + case SMB_LGRP_GTBL_SIDRID: + kgrp.sg_rid = va_arg(ap, uint32_t); + kgrp.sg_domain = va_arg(ap, smb_gdomain_t); + dom_idx = (kgrp.sg_domain == SMB_LGRP_LOCAL) + ? SMB_LGRP_LOCAL_IDX : SMB_LGRP_BUILTIN_IDX; + sql = sqlite_mprintf("SELECT * FROM groups" + "WHERE (sid_idx = %d) AND (sid_rid = %u)", + dom_idx, kgrp.sg_rid); + break; + + default: + va_end(ap); + return (SMB_LGRP_INVALID_ARG); + } + + va_end(ap); + if (sql == NULL) + return (SMB_LGRP_NO_MEMORY); + + rc = sqlite_get_table(db, sql, &result, &nrow, &ncol, &errmsg); + sqlite_freemem(sql); + + if (rc != SQLITE_OK) { + syslog(LOG_DEBUG, "failed to lookup (%s)", NULL_MSGCHK(errmsg)); + sqlite_freemem(errmsg); + return (SMB_LGRP_LOOKUP_FAILED); + } + + if (nrow == 0) { + /* group not found */ + sqlite_free_table(result); + return (SMB_LGRP_NOT_FOUND); + } + + if (nrow != 1 || ncol != SMB_LGRP_GTBL_NCOL) { + sqlite_free_table(result); + return (SMB_LGRP_DB_ERROR); + } + + rc = smb_lgrp_decode(grp, &result[SMB_LGRP_GTBL_NCOL], infolvl, db); + sqlite_free_table(result); + return (rc); +} + +/* + * smb_lgrp_gtbl_exists + * + * Checks to see if the given group exists or not. + */ +static boolean_t +smb_lgrp_gtbl_exists(sqlite *db, char *gname) +{ + char *errmsg = NULL; + char *sql; + char **result; + int nrow, ncol; + int rc; + + if (db == NULL) + return (NULL); + + sql = sqlite_mprintf("SELECT name FROM groups WHERE name = '%s'", + gname); + rc = sqlite_get_table(db, sql, &result, &nrow, &ncol, &errmsg); + sqlite_freemem(sql); + + if (rc != SQLITE_OK) { + syslog(LOG_DEBUG, "failed to lookup %s (%s)", + gname, NULL_MSGCHK(errmsg)); + sqlite_freemem(errmsg); + return (B_FALSE); + } + + sqlite_free_table(result); + return (nrow != 0); +} + +/* + * smb_lgrp_gtbl_count + * + * Counts the number of groups in the domain specified by + * 'dom_idx' + */ +static int +smb_lgrp_gtbl_count(sqlite *db, int dom_idx, int *count) +{ + char *errmsg = NULL; + char *sql; + char **result; + int nrow, ncol; + int rc; + + *count = 0; + if (db == NULL) + return (SMB_LGRP_DBOPEN_FAILED); + + sql = sqlite_mprintf("SELECT sid_idx FROM groups WHERE sid_idx = %d", + dom_idx); + rc = sqlite_get_table(db, sql, &result, &nrow, &ncol, &errmsg); + sqlite_freemem(sql); + + if (rc != SQLITE_OK) { + syslog(LOG_DEBUG, "failed to count (%s)", NULL_MSGCHK(errmsg)); + sqlite_freemem(errmsg); + return (SMB_LGRP_LOOKUP_FAILED); + } + + sqlite_free_table(result); + if (ncol != 1) + return (SMB_LGRP_DB_ERROR); + + *count = nrow; + return (SMB_LGRP_SUCCESS); +} + +/* + * smb_lgrp_gtbl_insert + * + * Insert a record for the given group in the group database. + * + * NOTE: this function assumes that this group has no members + * at this time. + */ +static int +smb_lgrp_gtbl_insert(sqlite *db, smb_group_t *grp) +{ + smb_lgpid_t privs[SE_MAX_LUID + 1]; + smb_lgplist_t plist; + char *errmsg = NULL; + char *sql; + int dom_idx; + int rc; + + if (db == NULL) + return (SMB_LGRP_DBOPEN_FAILED); + + dom_idx = (grp->sg_domain == SMB_LGRP_LOCAL) + ? SMB_LGRP_LOCAL_IDX : SMB_LGRP_BUILTIN_IDX; + + plist.p_cnt = SE_MAX_LUID; + plist.p_ids = privs; + smb_lgrp_encode_privset(grp, &plist); + + sql = sqlite_mprintf("INSERT INTO groups" + "(name, sid_idx, sid_rid, sid_type, sid_attrs, comment, " + "n_privs, privs, n_members, members) " + "VALUES('%s', %u, %u, %u, %u, '%q', %u, '%q', %u, '%q')", + grp->sg_name, dom_idx, grp->sg_rid, grp->sg_id.gs_type, + grp->sg_attr, (grp->sg_cmnt) ? grp->sg_cmnt : "", + plist.p_cnt, (char *)plist.p_ids, 0, ""); + + if (sql == NULL) + return (SMB_LGRP_NO_MEMORY); + + rc = sqlite_exec(db, sql, NULL, NULL, &errmsg); + sqlite_freemem(sql); + + if (rc != SQLITE_OK) { + syslog(LOG_DEBUG, "failed to insert %s (%s)", + grp->sg_name, NULL_MSGCHK(errmsg)); + sqlite_freemem(errmsg); + rc = SMB_LGRP_INSERT_FAILED; + } else { + rc = SMB_LGRP_SUCCESS; + } + + return (rc); +} + +/* + * smb_lgrp_gtbl_delete + * + * Removes the specified group from the database + */ +static int +smb_lgrp_gtbl_delete(sqlite *db, char *gname) +{ + char *errmsg = NULL; + char *sql; + int rc; + + if (db == NULL) + return (SMB_LGRP_DBOPEN_FAILED); + + sql = sqlite_mprintf("DELETE FROM groups WHERE name = '%s'", gname); + if (sql == NULL) + return (SMB_LGRP_NO_MEMORY); + + rc = sqlite_exec(db, sql, NULL, NULL, &errmsg); + sqlite_freemem(sql); + + if (rc != SQLITE_OK) { + syslog(LOG_DEBUG, "failed to delete %s (%s)", + gname, NULL_MSGCHK(errmsg)); + sqlite_freemem(errmsg); + rc = SMB_LGRP_DELETE_FAILED; + } else { + rc = SMB_LGRP_SUCCESS; + } + + return (rc); +} + +/* + * smb_lgrp_gtbl_update + * + * Updates the specified group information, the supported items + * are group name and comment + */ +static int +smb_lgrp_gtbl_update(sqlite *db, char *gname, smb_group_t *grp, int col_id) +{ + char *errmsg = NULL; + char *sql; + int rc; + + if (db == NULL) + return (SMB_LGRP_DBOPEN_FAILED); + + /* UPDATE doesn't fail if gname doesn't exist */ + if (!smb_lgrp_gtbl_exists(db, gname)) + return (SMB_LGRP_NOT_FOUND); + + switch (col_id) { + case SMB_LGRP_GTBL_NAME: + if (smb_lgrp_gtbl_exists(db, grp->sg_name)) + return (SMB_LGRP_EXISTS); + sql = sqlite_mprintf("UPDATE groups SET name = '%s' " + "WHERE name = '%s'", grp->sg_name, gname); + break; + + case SMB_LGRP_GTBL_CMNT: + sql = sqlite_mprintf("UPDATE groups SET comment = '%q' " + "WHERE name = '%s'", grp->sg_cmnt, gname); + break; + + default: + return (SMB_LGRP_INVALID_ARG); + } + + if (sql == NULL) + return (SMB_LGRP_NO_MEMORY); + + rc = sqlite_exec(db, sql, NULL, NULL, &errmsg); + sqlite_freemem(sql); + + if (rc != SQLITE_OK) { + syslog(LOG_DEBUG, "failed to update %s (%s)", + gname, NULL_MSGCHK(errmsg)); + sqlite_freemem(errmsg); + rc = SMB_LGRP_UPDATE_FAILED; + } else { + rc = SMB_LGRP_SUCCESS; + } + + return (rc); +} + +/* + * smb_lgrp_gtbl_update_mlist + * + * Adds/removes the specified member from the member list of the + * given group + */ +static int +smb_lgrp_gtbl_update_mlist(sqlite *db, char *gname, smb_gsid_t *member, + int flags) +{ + smb_lgmlist_t new_members; + smb_lgmlist_t members; + smb_lgmid_t mid; + char *errmsg = NULL; + char *sql; + char **result; + int nrow, ncol; + int rc; + + if (db == NULL) + return (SMB_LGRP_DBOPEN_FAILED); + + sql = sqlite_mprintf("SELECT n_members, members FROM groups " + "WHERE name = '%s'", gname); + + if (sql == NULL) + return (SMB_LGRP_NO_MEMORY); + + rc = sqlite_get_table(db, sql, &result, &nrow, &ncol, &errmsg); + sqlite_freemem(sql); + + if (rc != SQLITE_OK) { + syslog(LOG_DEBUG, "failed to lookup %s (%s)", + gname, NULL_MSGCHK(errmsg)); + sqlite_freemem(errmsg); + return (SMB_LGRP_LOOKUP_FAILED); + } + + if (nrow == 0) { + /* group not found */ + sqlite_free_table(result); + return (SMB_LGRP_NOT_FOUND); + } + + if (nrow != 1 || ncol != 2) { + sqlite_free_table(result); + return (SMB_LGRP_DB_ERROR); + } + + bzero(&mid, sizeof (mid)); + mid.m_type = member->gs_type; + rc = smb_lgrp_dtbl_getidx(db, member->gs_sid, mid.m_type, + &mid.m_idx, &mid.m_rid); + if (rc != SMB_LGRP_SUCCESS) { + sqlite_free_table(result); + return (rc); + } + + members.m_cnt = atoi(result[2]); + members.m_ids = result[3]; + + switch (flags) { + case SMB_LGRP_DB_ADDMEMBER: + rc = smb_lgrp_mlist_add(&members, &mid, &new_members); + break; + case SMB_LGRP_DB_DELMEMBER: + rc = smb_lgrp_mlist_del(&members, &mid, &new_members); + break; + default: + rc = SMB_LGRP_INVALID_ARG; + } + + sqlite_free_table(result); + if (rc != SMB_LGRP_SUCCESS) + return (rc); + + sql = sqlite_mprintf("UPDATE groups SET n_members = %u, members = '%s'" + " WHERE name = '%s'", new_members.m_cnt, new_members.m_ids, gname); + + free(new_members.m_ids); + + if (sql == NULL) + return (SMB_LGRP_NO_MEMORY); + + rc = sqlite_exec(db, sql, NULL, NULL, &errmsg); + sqlite_freemem(sql); + + if (rc != SQLITE_OK) { + syslog(LOG_DEBUG, "failed to update %s (%s)", gname, + NULL_MSGCHK(errmsg)); + sqlite_freemem(errmsg); + rc = SMB_LGRP_UPDATE_FAILED; + } else { + rc = SMB_LGRP_SUCCESS; + } + + return (rc); +} + +/* + * smb_lgrp_gtbl_update_plist + * + * Adds/removes the specified privilege from the privilege list of the + * given group + */ +static int +smb_lgrp_gtbl_update_plist(sqlite *db, char *gname, uint8_t priv_id, + boolean_t enable) +{ + char *sql; + char *errmsg = NULL; + char **result; + int nrow, ncol; + int rc; + smb_lgplist_t privs; + smb_lgplist_t new_privs; + + if (db == NULL) + return (SMB_LGRP_DBOPEN_FAILED); + + sql = sqlite_mprintf("SELECT n_privs, privs FROM groups " + "WHERE name = '%s'", gname); + + if (sql == NULL) + return (SMB_LGRP_NO_MEMORY); + + rc = sqlite_get_table(db, sql, &result, &nrow, &ncol, &errmsg); + sqlite_freemem(sql); + + if (rc != SQLITE_OK) { + syslog(LOG_DEBUG, "failed to lookup %s (%s)", + gname, NULL_MSGCHK(errmsg)); + sqlite_freemem(errmsg); + return (SMB_LGRP_LOOKUP_FAILED); + } + + if (nrow == 0) { + /* group not found */ + sqlite_free_table(result); + return (SMB_LGRP_NOT_FOUND); + } + + if (nrow != 1 || ncol != 2) { + sqlite_free_table(result); + return (SMB_LGRP_DB_ERROR); + } + + privs.p_cnt = atoi(result[2]); + privs.p_ids = (smb_lgpid_t *)result[3]; + + if (enable) + rc = smb_lgrp_plist_add(&privs, priv_id, &new_privs); + else + rc = smb_lgrp_plist_del(&privs, priv_id, &new_privs); + + sqlite_free_table(result); + if (rc != SMB_LGRP_SUCCESS) + return (rc); + + sql = sqlite_mprintf("UPDATE groups SET n_privs = %u, privs = '%q'" + " WHERE name = '%s'", new_privs.p_cnt, (char *)new_privs.p_ids, + gname); + + free(new_privs.p_ids); + + if (sql == NULL) + return (SMB_LGRP_NO_MEMORY); + + rc = sqlite_exec(db, sql, NULL, NULL, &errmsg); + sqlite_freemem(sql); + + if (rc != SQLITE_OK) { + syslog(LOG_DEBUG, "failed to update %s (%s)", + gname, NULL_MSGCHK(errmsg)); + sqlite_freemem(errmsg); + rc = SMB_LGRP_UPDATE_FAILED; + } else { + rc = SMB_LGRP_SUCCESS; + } + + return (rc); +} + +/* + * smb_lgrp_dtbl_insert + * + * Inserts the specified domain SID in the dmain table. + * Upon successful insert the index will be returned in + * 'dom_idx' arg. + */ +static int +smb_lgrp_dtbl_insert(sqlite *db, char *dom_sid, uint32_t *dom_idx) +{ + char *errmsg = NULL; + char *sql; + int rc; + + sql = sqlite_mprintf("INSERT INTO domains (dom_sid, dom_cnt)" + " VALUES('%s', 1);", dom_sid); + if (sql == NULL) + return (SMB_LGRP_NO_MEMORY); + + rc = sqlite_exec(db, sql, NULL, NULL, &errmsg); + sqlite_freemem(sql); + + if (rc != SQLITE_OK) { + syslog(LOG_DEBUG, "failed to insert domain SID (%s)", + NULL_MSGCHK(errmsg)); + sqlite_freemem(errmsg); + return (SMB_LGRP_DOMINS_FAILED); + } + + if (dom_idx) + *dom_idx = sqlite_last_insert_rowid(db); + return (SMB_LGRP_SUCCESS); +} + +/* + * smb_lgrp_dtbl_getidx + * + * Searches the domain table for the domain SID of the + * given member SID. If it finds the domain SID it'll + * return the index and the RID, otherwise it'll insert + * it in the domain table as a new SID. + */ +static int +smb_lgrp_dtbl_getidx(sqlite *db, nt_sid_t *sid, uint16_t sid_type, + uint32_t *dom_idx, uint32_t *rid) +{ + char sidstr[NT_SID_FMTBUF_SIZE]; + nt_sid_t *dom_sid; + char **result; + int nrow, ncol; + char *errmsg = NULL; + char *sql; + int rc; + + if (nt_sid_is_indomain(smb_lgrp_lsid, sid)) { + /* This is a local SID */ + int id_type = (sid_type == SidTypeUser) + ? SMB_IDMAP_USER : SMB_IDMAP_GROUP; + *dom_idx = SMB_LGRP_LOCAL_IDX; + if (smb_idmap_getid(sid, rid, &id_type) != IDMAP_SUCCESS) + return (SMB_LGRP_INTERNAL_ERROR); + } + + dom_sid = nt_sid_dup(sid); + if (dom_sid == NULL) + return (SMB_LGRP_NO_MEMORY); + + (void) nt_sid_split(dom_sid, rid); + nt_sid_format2(dom_sid, sidstr); + free(dom_sid); + + sql = sqlite_mprintf("SELECT dom_idx FROM domains WHERE dom_sid = '%s'", + sidstr); + if (sql == NULL) + return (SMB_LGRP_NO_MEMORY); + + rc = sqlite_get_table(db, sql, &result, &nrow, &ncol, &errmsg); + sqlite_freemem(sql); + + if (rc != SQLITE_OK) { + syslog(LOG_DEBUG, "failed to lookup domain SID (%s)", + NULL_MSGCHK(errmsg)); + sqlite_freemem(errmsg); + return (SMB_LGRP_DOMLKP_FAILED); + } + + switch (nrow) { + case 0: + /* new domain SID; insert it into the domains table */ + sqlite_free_table(result); + return (smb_lgrp_dtbl_insert(db, sidstr, dom_idx)); + + case 1: + *dom_idx = atoi(result[1]); + sqlite_free_table(result); + return (SMB_LGRP_SUCCESS); + } + + sqlite_free_table(result); + return (SMB_LGRP_DB_ERROR); +} + +/* + * smb_lgrp_dtbl_getsid + * + * Searchs the domain table for the given domain index. + * Converts the found domain SID to binary format and + * returns it in the 'sid' arg. + * + * Caller must free the returned SID by calling free(). + */ +static int +smb_lgrp_dtbl_getsid(sqlite *db, uint32_t dom_idx, nt_sid_t **sid) +{ + char **result; + int nrow, ncol; + char *errmsg = NULL; + char *sql; + int rc; + + sql = sqlite_mprintf("SELECT dom_sid FROM domains WHERE dom_idx = %u", + dom_idx); + if (sql == NULL) + return (SMB_LGRP_NO_MEMORY); + + rc = sqlite_get_table(db, sql, &result, &nrow, &ncol, &errmsg); + sqlite_freemem(sql); + + if (rc != SQLITE_OK) { + syslog(LOG_DEBUG, "failed to lookup domain index (%s)", + NULL_MSGCHK(errmsg)); + sqlite_freemem(errmsg); + return (SMB_LGRP_DOMLKP_FAILED); + } + + switch (nrow) { + case 0: + rc = SMB_LGRP_NO_SUCH_DOMAIN; + break; + + case 1: + *sid = nt_sid_strtosid(result[1]); + rc = (*sid == NULL) + ? SMB_LGRP_INTERNAL_ERROR : SMB_LGRP_SUCCESS; + break; + + default: + rc = SMB_LGRP_DB_ERROR; + break; + } + + sqlite_free_table(result); + return (rc); +} + +/* + * smb_lgrp_db_setinfo + * + * Initializes the db_info table upon database creation. + */ +static int +smb_lgrp_db_setinfo(sqlite *db) +{ + char *errmsg = NULL; + char *sql; + int rc; + + sql = sqlite_mprintf("INSERT INTO db_info (ver_major, ver_minor," + " magic) VALUES (%d, %d, %u)", SMB_LGRP_DB_VERMAJOR, + SMB_LGRP_DB_VERMINOR, SMB_LGRP_DB_MAGIC); + + if (sql == NULL) + return (SMB_LGRP_NO_MEMORY); + + rc = sqlite_exec(db, sql, NULL, NULL, &errmsg); + sqlite_freemem(sql); + if (rc != SQLITE_OK) { + syslog(LOG_DEBUG, "failed to insert database information (%s)", + NULL_MSGCHK(errmsg)); + sqlite_freemem(errmsg); + rc = SMB_LGRP_DBINIT_ERROR; + } else { + rc = SMB_LGRP_SUCCESS; + } + + return (rc); +} + +/* + * smb_lgrp_mlist_add + * + * Adds the given member (newm) to the input member list (in_members) + * if it's not already there. The result list will be returned in + * out_members. The caller must free the allocated memory for + * out_members by calling free(). + * + * in_members and out_members are hex strings. + */ +static int +smb_lgrp_mlist_add(smb_lgmlist_t *in_members, smb_lgmid_t *newm, + smb_lgmlist_t *out_members) +{ + char mid_hex[SMB_LGRP_MID_HEXSZ]; + char *in_list; + char *out_list; + int in_size; + int out_size; + int mid_hexsz; + int i; + + out_members->m_cnt = 0; + out_members->m_ids = NULL; + + bzero(mid_hex, sizeof (mid_hex)); + mid_hexsz = bintohex((const char *)newm, sizeof (smb_lgmid_t), + mid_hex, sizeof (mid_hex)); + + /* + * Check to see if this is already a group member + */ + in_list = in_members->m_ids; + for (i = 0; i < in_members->m_cnt; i++) { + if (strncmp(in_list, mid_hex, mid_hexsz) == 0) + return (SMB_LGRP_MEMBER_IN_GROUP); + in_list += mid_hexsz; + } + + in_size = (in_members->m_ids) ? strlen(in_members->m_ids) : 0; + out_size = in_size + sizeof (mid_hex) + 1; + out_list = malloc(out_size); + if (out_list == NULL) + return (SMB_LGRP_NO_MEMORY); + + bzero(out_list, out_size); + if (in_members->m_ids) + (void) strlcpy(out_list, in_members->m_ids, out_size); + (void) strcat(out_list, mid_hex); + + out_members->m_cnt = in_members->m_cnt + 1; + out_members->m_ids = out_list; + + return (SMB_LGRP_SUCCESS); +} + +/* + * smb_lgrp_mlist_del + * + * Removes the given member (msid) from the input member list + * (in_members) if it's already there. The result list will b + * returned in out_members. The caller must free the allocated + * memory for out_members by calling free(). + * + * in_members and out_members are hex strings. + */ +static int +smb_lgrp_mlist_del(smb_lgmlist_t *in_members, smb_lgmid_t *mid, + smb_lgmlist_t *out_members) +{ + char mid_hex[SMB_LGRP_MID_HEXSZ]; + char *in_list; + char *out_list; + int in_size; + int out_size; + int mid_hexsz; + int out_cnt; + int i; + + out_members->m_cnt = 0; + out_members->m_ids = NULL; + + if ((in_members == NULL) || (in_members->m_cnt == 0)) + return (SMB_LGRP_MEMBER_NOT_IN_GROUP); + + in_size = strlen(in_members->m_ids); + out_size = in_size + sizeof (mid_hex) + 1; + out_list = malloc(out_size); + if (out_list == NULL) + return (SMB_LGRP_NO_MEMORY); + + *out_list = '\0'; + + bzero(mid_hex, sizeof (mid_hex)); + mid_hexsz = bintohex((const char *)mid, sizeof (smb_lgmid_t), + mid_hex, sizeof (mid_hex)); + + in_list = in_members->m_ids; + for (i = 0, out_cnt = 0; i < in_members->m_cnt; i++) { + if (strncmp(in_list, mid_hex, mid_hexsz)) { + (void) strncat(out_list, in_list, mid_hexsz); + out_cnt++; + } + in_list += mid_hexsz; + } + + if (out_cnt == in_members->m_cnt) { + free(out_list); + return (SMB_LGRP_MEMBER_NOT_IN_GROUP); + } + + out_members->m_cnt = out_cnt; + out_members->m_ids = out_list; + return (SMB_LGRP_SUCCESS); +} + +/* + * smb_lgrp_plist_add + * + * Adds the given privilege to the input list (in_privs) + * if it's not already there. The result list is returned + * in out_privs. The caller must free the allocated memory + * for out_privs by calling free(). + */ +static int +smb_lgrp_plist_add(smb_lgplist_t *in_privs, smb_lgpid_t priv_id, + smb_lgplist_t *out_privs) +{ + int i, size; + smb_lgpid_t *pbuf; + + out_privs->p_cnt = 0; + out_privs->p_ids = NULL; + + for (i = 0; i < in_privs->p_cnt; i++) { + if (in_privs->p_ids[i] == priv_id) + return (SMB_LGRP_PRIV_HELD); + } + + size = (in_privs->p_cnt + 1) * sizeof (smb_lgpid_t) + 1; + pbuf = malloc(size); + if (pbuf == NULL) + return (SMB_LGRP_NO_MEMORY); + + bzero(pbuf, size); + bcopy(in_privs->p_ids, pbuf, in_privs->p_cnt * sizeof (smb_lgpid_t)); + pbuf[in_privs->p_cnt] = priv_id; + + out_privs->p_cnt = in_privs->p_cnt + 1; + out_privs->p_ids = pbuf; + + return (SMB_LGRP_SUCCESS); +} + +/* + * smb_lgrp_plist_del + * + * Removes the given privilege from the input list (in_privs) + * if it's already there. The result list is returned + * in out_privs. The caller must free the allocated memory + * for out_privs by calling free(). + */ +static int +smb_lgrp_plist_del(smb_lgplist_t *in_privs, smb_lgpid_t priv_id, + smb_lgplist_t *out_privs) +{ + int i, size; + + out_privs->p_cnt = 0; + out_privs->p_ids = NULL; + + if ((in_privs == NULL) || (in_privs->p_cnt == 0)) + return (SMB_LGRP_PRIV_NOT_HELD); + + size = (in_privs->p_cnt - 1) * sizeof (smb_lgpid_t) + 1; + out_privs->p_ids = malloc(size); + if (out_privs->p_ids == NULL) + return (SMB_LGRP_NO_MEMORY); + + bzero(out_privs->p_ids, size); + + for (i = 0; i < in_privs->p_cnt; i++) { + if (in_privs->p_ids[i] != priv_id) + out_privs->p_ids[out_privs->p_cnt++] = + in_privs->p_ids[i]; + } + + if (out_privs->p_cnt == in_privs->p_cnt) { + free(out_privs->p_ids); + out_privs->p_cnt = 0; + out_privs->p_ids = NULL; + return (SMB_LGRP_PRIV_NOT_HELD); + } + + return (SMB_LGRP_SUCCESS); +} + +/* + * smb_lgrp_encode_privset + * + * Encodes given privilege set into a buffer to be stored in the group + * database. Each entry of the encoded buffer contains the privilege ID + * of an enable privilege. The returned buffer is null-terminated. + */ +static void +smb_lgrp_encode_privset(smb_group_t *grp, smb_lgplist_t *plist) +{ + smb_privset_t *privs; + uint32_t pcnt = plist->p_cnt; + int i; + + bzero(plist->p_ids, sizeof (smb_lgpid_t) * plist->p_cnt); + plist->p_cnt = 0; + + privs = grp->sg_privs; + if ((privs == NULL) || (privs->priv_cnt == 0)) + return; + + if (pcnt < privs->priv_cnt) { + assert(0); + } + + for (i = 0; i < privs->priv_cnt; i++) { + if (privs->priv[i].attrs == SE_PRIVILEGE_ENABLED) { + plist->p_ids[plist->p_cnt++] = + (uint8_t)privs->priv[i].luid.lo_part; + } + } +} + +/* + * smb_lgrp_decode_privset + * + * Decodes the privilege information read from group table + * (nprivs, privs) into a binray format specified by the + * privilege field of smb_group_t + */ +static int +smb_lgrp_decode_privset(smb_group_t *grp, char *nprivs, char *privs) +{ + smb_lgplist_t plist; + int i; + + plist.p_cnt = atoi(nprivs); + if (strlen(privs) != plist.p_cnt) + return (SMB_LGRP_BAD_DATA); + + plist.p_ids = (smb_lgpid_t *)privs; + grp->sg_privs = smb_privset_new(); + if (grp->sg_privs == NULL) + return (SMB_LGRP_NO_MEMORY); + + for (i = 0; i < plist.p_cnt; i++) + smb_privset_enable(grp->sg_privs, plist.p_ids[i]); + + return (SMB_LGRP_SUCCESS); +} + +/* + * smb_lgrp_decode_members + * + * Decodes the members information read from group table + * (nmembers, members) into a binray format specified by the + * member fields of smb_group_t + */ +static int +smb_lgrp_decode_members(smb_group_t *grp, char *nmembers, char *members, + sqlite *db) +{ + smb_lgmid_t *m_ids; + smb_lgmid_t *mid; + smb_gsid_t *member; + int mids_size; + int i, rc; + + grp->sg_nmembers = atoi(nmembers); + mids_size = grp->sg_nmembers * sizeof (smb_lgmid_t); + m_ids = malloc(mids_size); + if (m_ids == NULL) + return (SMB_LGRP_NO_MEMORY); + + grp->sg_members = malloc(grp->sg_nmembers * sizeof (smb_gsid_t)); + if (grp->sg_members == NULL) { + free(m_ids); + return (SMB_LGRP_NO_MEMORY); + } + + (void) hextobin(members, strlen(members), (char *)m_ids, mids_size); + + mid = m_ids; + member = grp->sg_members; + for (i = 0; i < grp->sg_nmembers; i++, mid++, member++) { + rc = smb_lgrp_getsid(mid->m_idx, &mid->m_rid, mid->m_type, db, + &member->gs_sid); + if (rc != SMB_LGRP_SUCCESS) { + free(m_ids); + return (SMB_LGRP_DB_ERROR); + } + + member->gs_type = mid->m_type; + } + + free(m_ids); + return (SMB_LGRP_SUCCESS); +} + +/* + * smb_lgrp_decode + * + * Fills out the fields of the given group (grp) based in the + * string information read from the group table. infolvl determines + * which fields are requested and need to be decoded. + * + * Allocated memories must be freed by calling smb_lgrp_free() + * upon successful return. + */ +static int +smb_lgrp_decode(smb_group_t *grp, char **values, int infolvl, sqlite *db) +{ + uint32_t sid_idx; + int rc; + + if (infolvl == SMB_LGRP_INFO_NONE) + return (SMB_LGRP_SUCCESS); + + if (infolvl & SMB_LGRP_INFO_NAME) { + grp->sg_name = strdup(values[SMB_LGRP_GTBL_NAME]); + if (grp->sg_name == NULL) + return (SMB_LGRP_NO_MEMORY); + } + + if (infolvl & SMB_LGRP_INFO_CMNT) { + grp->sg_cmnt = strdup(values[SMB_LGRP_GTBL_CMNT]); + if (grp->sg_cmnt == NULL) { + smb_lgrp_free(grp); + return (SMB_LGRP_NO_MEMORY); + } + } + + + if (infolvl & SMB_LGRP_INFO_SID) { + sid_idx = atoi(values[SMB_LGRP_GTBL_SIDIDX]); + grp->sg_rid = atoi(values[SMB_LGRP_GTBL_SIDRID]); + grp->sg_attr = atoi(values[SMB_LGRP_GTBL_SIDATR]); + grp->sg_id.gs_type = atoi(values[SMB_LGRP_GTBL_SIDTYP]); + rc = smb_lgrp_getsid(sid_idx, &grp->sg_rid, grp->sg_id.gs_type, + db, &grp->sg_id.gs_sid); + if (rc != SMB_LGRP_SUCCESS) { + smb_lgrp_free(grp); + return (SMB_LGRP_NO_MEMORY); + } + grp->sg_domain = (sid_idx == SMB_LGRP_LOCAL_IDX) + ? SMB_LGRP_LOCAL : SMB_LGRP_BUILTIN; + } + + if (infolvl & SMB_LGRP_INFO_PRIV) { + rc = smb_lgrp_decode_privset(grp, values[SMB_LGRP_GTBL_NPRIVS], + values[SMB_LGRP_GTBL_PRIVS]); + + if (rc != SMB_LGRP_SUCCESS) { + smb_lgrp_free(grp); + return (rc); + } + } + + if (infolvl & SMB_LGRP_INFO_MEMB) { + rc = smb_lgrp_decode_members(grp, values[SMB_LGRP_GTBL_NMEMBS], + values[SMB_LGRP_GTBL_MEMBS], db); + if (rc != SMB_LGRP_SUCCESS) { + smb_lgrp_free(grp); + return (rc); + } + } + + return (SMB_LGRP_SUCCESS); +} + +/* + * 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. + * + * Source: MSDN, description of NetLocalGroupAdd function. + */ +static boolean_t +smb_lgrp_chkname(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); + + len = strlen(name); + if (len > SMB_LGRP_NAME_MAX) + 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) utf8_strlwr(name); + return (B_TRUE); +} + +/* + * smb_lgrp_set_default_privs + * + * set default privileges for Administrators and Backup Operators + */ +static void +smb_lgrp_set_default_privs(smb_group_t *grp) +{ + if (utf8_strcasecmp(grp->sg_name, "Administrators") == 0) { + smb_privset_enable(grp->sg_privs, SE_TAKE_OWNERSHIP_LUID); + return; + } + + if (utf8_strcasecmp(grp->sg_name, "Backup Operators") == 0) { + smb_privset_enable(grp->sg_privs, SE_BACKUP_LUID); + smb_privset_enable(grp->sg_privs, SE_RESTORE_LUID); + return; + } +} + +/* + * smb_lgrp_getsid + * + * Returns a SID based on the provided information + * If dom_idx is 0, it means 'rid' contains a UID/GID and the + * returned SID will be a local SID. If dom_idx is not 0 then + * the domain SID will be fetched from the domain table. + */ +static int +smb_lgrp_getsid(int dom_idx, uint32_t *rid, uint16_t sid_type, + sqlite *db, nt_sid_t **sid) +{ + nt_sid_t *dom_sid = NULL; + nt_sid_t *res_sid = NULL; + int id_type; + int rc; + + *sid = NULL; + if (dom_idx == SMB_LGRP_LOCAL_IDX) { + id_type = (sid_type == SidTypeUser) + ? SMB_IDMAP_USER : SMB_IDMAP_GROUP; + if (smb_idmap_getsid(*rid, id_type, &res_sid) != IDMAP_SUCCESS) + return (SMB_LGRP_NO_SID); + + /* + * Make sure the returned SID is local + */ + if (!nt_sid_is_indomain(smb_lgrp_lsid, res_sid)) { + free(res_sid); + return (SMB_LGRP_SID_NOTLOCAL); + } + + (void) nt_sid_get_rid(res_sid, rid); + *sid = res_sid; + return (SMB_LGRP_SUCCESS); + } + + rc = smb_lgrp_dtbl_getsid(db, dom_idx, &dom_sid); + if (rc != SMB_LGRP_SUCCESS) + return (SMB_LGRP_DB_ERROR); + + res_sid = nt_sid_splice(dom_sid, *rid); + free(dom_sid); + if (res_sid == NULL) + return (SMB_LGRP_NO_MEMORY); + + *sid = res_sid; + return (SMB_LGRP_SUCCESS); +} diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_privilege.c b/usr/src/lib/smbsrv/libsmb/common/smb_privilege.c index ce7cef198a..be8853f4bc 100644 --- a/usr/src/lib/smbsrv/libsmb/common/smb_privilege.c +++ b/usr/src/lib/smbsrv/libsmb/common/smb_privilege.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -41,9 +41,6 @@ #include <smbsrv/libsmb.h> #include <smbsrv/smb_privilege.h> -#define SMB_PRIV_MIN 2 -#define SMB_PRIV_MAX 24 - static char *smb_priv_getname(uint32_t id); /* @@ -98,7 +95,7 @@ smb_priv_presentable_num() int i, num; num = 0; - for (i = SMB_PRIV_MIN; i <= SMB_PRIV_MAX; i++) + for (i = SE_MIN_LUID; i <= SE_MAX_LUID; i++) if (priv_table[i].flags == PF_PRESENTABLE) num++; @@ -119,7 +116,7 @@ smb_priv_presentable_ids(uint32_t *ids, int num) if (ids == NULL || num <= 0) return (0); - for (i = SMB_PRIV_MIN, j = 0; i <= SMB_PRIV_MAX; i++) + for (i = SE_MIN_LUID, j = 0; i <= SE_MAX_LUID; i++) if (priv_table[i].flags == PF_PRESENTABLE) ids[j++] = priv_table[i].id; @@ -135,7 +132,7 @@ smb_priv_presentable_ids(uint32_t *ids, int num) smb_privinfo_t * smb_priv_getbyvalue(uint32_t id) { - if (id < SMB_PRIV_MIN || id > SMB_PRIV_MAX) + if (id < SE_MIN_LUID || id > SE_MAX_LUID) return (0); return (&priv_table[id]); @@ -157,7 +154,7 @@ smb_priv_getbyname(char *name) if (name == 0) return (0); - for (i = SMB_PRIV_MIN; i <= SMB_PRIV_MAX; ++i) { + for (i = SE_MIN_LUID; i <= SE_MAX_LUID; ++i) { entry = &priv_table[i]; if (utf8_strcasecmp(name, entry->name) == 0) @@ -176,7 +173,7 @@ smb_priv_getbyname(char *name) int smb_privset_size() { - int pcnt = SMB_PRIV_MAX - SMB_PRIV_MIN + 1; + int pcnt = SE_MAX_LUID - SE_MIN_LUID + 1; return (2 * sizeof (uint32_t) + pcnt * sizeof (smb_luid_attrs_t)); @@ -198,7 +195,7 @@ smb_privset_validate(smb_privset_t *privset) return (0); } - count = SMB_PRIV_MAX - SMB_PRIV_MIN + 1; + count = SE_MAX_LUID - SE_MIN_LUID + 1; if (privset->priv_cnt != count) { return (0); @@ -210,7 +207,7 @@ smb_privset_validate(smb_privset_t *privset) } if (privset->priv[i].luid.lo_part != - i + SMB_PRIV_MIN) { + i + SE_MIN_LUID) { return (0); } } @@ -232,13 +229,13 @@ smb_privset_init(smb_privset_t *privset) if (privset == 0) return; - count = SMB_PRIV_MAX - SMB_PRIV_MIN + 1; + count = SE_MAX_LUID - SE_MIN_LUID + 1; privset->priv_cnt = count; privset->control = 0; for (i = 0; i < count; i++) { privset->priv[i].luid.hi_part = 0; - privset->priv[i].luid.lo_part = i + SMB_PRIV_MIN; + privset->priv[i].luid.lo_part = i + SE_MIN_LUID; privset->priv[i].attrs = 0; } } @@ -280,6 +277,25 @@ smb_privset_copy(smb_privset_t *dst, smb_privset_t *src) } /* + * smb_privset_merge + * + * Enable the privileges that are enabled in src in dst + */ +void +smb_privset_merge(smb_privset_t *dst, smb_privset_t *src) +{ + int i; + + if (src == NULL || dst == NULL) + return; + + for (i = 0; i < src->priv_cnt; i++) { + if (src->priv[i].attrs == SE_PRIVILEGE_ENABLED) + smb_privset_enable(dst, src->priv[i].luid.lo_part); + } +} + +/* * smb_privset_free * * This will free the memory allocated by the 'privset'. @@ -354,7 +370,7 @@ smb_privset_query(smb_privset_t *privset, uint32_t id) static char * smb_priv_getname(uint32_t id) { - if (id < SMB_PRIV_MIN || id > SMB_PRIV_MAX) + if (id < SE_MIN_LUID || id > SE_MAX_LUID) return ("Unknown Privilege"); return (priv_table[id].name); diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_pwdutil.c b/usr/src/lib/smbsrv/libsmb/common/smb_pwdutil.c index 10026d7418..cc0cddebcd 100644 --- a/usr/src/lib/smbsrv/libsmb/common/smb_pwdutil.c +++ b/usr/src/lib/smbsrv/libsmb/common/smb_pwdutil.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -173,8 +173,7 @@ smb_pwd_update(const char *name, const char *password, int control) boolean_t user_disable = B_FALSE; char uxbuf[1024]; struct passwd uxpw; - int lm_level; - char *lm_str; + int64_t lm_level; err = smb_pwd_lock(); if (err != SMB_PWE_SUCCESS) @@ -202,13 +201,8 @@ smb_pwd_update(const char *name, const char *password, int control) goto passwd_exit; } - lm_str = smb_config_getenv(SMB_CI_LM_LEVEL); - if (lm_str) { - lm_level = strtoul(lm_str, 0, 10); - free(lm_str); - } else { + if (smb_config_getnum(SMB_CI_LM_LEVEL, &lm_level) != SMBD_SMF_OK) lm_level = 4; - } if (lm_level >= 4) control |= SMB_PWC_NOLM; diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_scfutil.c b/usr/src/lib/smbsrv/libsmb/common/smb_scfutil.c index 1f5083f448..4460e70154 100644 --- a/usr/src/lib/smbsrv/libsmb/common/smb_scfutil.c +++ b/usr/src/lib/smbsrv/libsmb/common/smb_scfutil.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -60,95 +60,6 @@ smb_smf_scf_log_error(char *msg) } /* - * Check if instance with given name exists for a service. - * Returns 0 is instance exist - */ -int -smb_smf_instance_exists(smb_scfhandle_t *handle, char *inst_name) -{ - int ret = SMBD_SMF_OK; - if (handle == NULL) - return (SMBD_SMF_SYSTEM_ERR); - - handle->scf_instance = scf_instance_create(handle->scf_handle); - if (scf_service_get_instance(handle->scf_service, inst_name, - handle->scf_instance) != SCF_SUCCESS) - ret = SMBD_SMF_SYSTEM_ERR; - - scf_instance_destroy(handle->scf_instance); - handle->scf_instance = NULL; - return (ret); -} - -/* - * Create a service instance. returns 0 if successful. - * If instance already exists enable it. - */ -int -smb_smf_instance_create(smb_scfhandle_t *handle, char *serv_prefix, - char *inst_name) -{ - char *instance; - int ret = SMBD_SMF_OK; - int sz; - - if (handle == NULL) - return (SMBD_SMF_SYSTEM_ERR); - - if (!serv_prefix || !inst_name) - return (SMBD_SMF_SYSTEM_ERR); - - sz = strlen(serv_prefix) + strlen(inst_name) + 2; - instance = malloc(sz); - if (!instance) - return (SMBD_SMF_NO_MEMORY); - - (void) snprintf(instance, sz, "%s:%s", serv_prefix, inst_name); - handle->scf_instance = scf_instance_create(handle->scf_handle); - if (scf_service_get_instance(handle->scf_service, inst_name, - handle->scf_instance) != SCF_SUCCESS) { - if (scf_service_add_instance(handle->scf_service, - inst_name, handle->scf_instance) == SCF_SUCCESS) { - if (smf_enable_instance(instance, 0)) - ret = SMBD_SMF_SYSTEM_ERR; - } else { - ret = SMBD_SMF_SYSTEM_ERR; - } - } else { - if (smf_enable_instance(instance, 0)) - ret = SMBD_SMF_SYSTEM_ERR; - } - free(instance); - return (ret); -} - -/* - * Delete a specified instance. Return SMBD_SMF_OK for success. - */ -int -smb_smf_instance_delete(smb_scfhandle_t *handle, char *inst_name) -{ - int ret = SMBD_SMF_OK; - - if (handle == NULL) - return (SMBD_SMF_SYSTEM_ERR); - - handle->scf_instance = scf_instance_create(handle->scf_handle); - if (scf_service_get_instance(handle->scf_service, inst_name, - handle->scf_instance) == SCF_SUCCESS) { - if (scf_instance_delete(handle->scf_instance) == SCF_SUCCESS) { - return (ret); - } else { - ret = SMBD_SMF_SYSTEM_ERR; - } - } else { - smb_smf_scf_log_error(NULL); - ret = SMBD_SMF_SYSTEM_ERR; - } - return (ret); -} - -/* * smb_smf_create_service_pgroup(handle, pgroup) * * create a new property group at service level. @@ -196,152 +107,6 @@ smb_smf_create_service_pgroup(smb_scfhandle_t *handle, char *pgroup) } /* - * smb_smf_create_instance_pgroup(handle, pgroup) - * - * create a new property group at instance level. - */ -int -smb_smf_create_instance_pgroup(smb_scfhandle_t *handle, char *pgroup) -{ - int ret = SMBD_SMF_OK; - int err; - - if (handle == NULL) { - return (SMBD_SMF_SYSTEM_ERR); - } - - /* - * only create a handle if it doesn't exist. It is ok to exist - * since the pg handle will be set as a side effect. - */ - if (handle->scf_pg == NULL) - handle->scf_pg = scf_pg_create(handle->scf_handle); - - /* - * if the pgroup exists, we are done. If it doesn't, then we - * need to actually add one to the service instance. - */ - if (scf_instance_get_pg(handle->scf_instance, - pgroup, handle->scf_pg) != 0) { - /* doesn't exist so create one */ - if (scf_instance_add_pg(handle->scf_instance, pgroup, - SCF_GROUP_FRAMEWORK, 0, handle->scf_pg) != 0) { - err = scf_error(); - if (err != SCF_ERROR_NONE) - smb_smf_scf_log_error(NULL); - switch (err) { - case SCF_ERROR_PERMISSION_DENIED: - ret = SMBD_SMF_NO_PERMISSION; - break; - default: - ret = SMBD_SMF_SYSTEM_ERR; - break; - } - } - } - return (ret); -} - -/* - * smb_smf_delete_service_pgroup(handle, pgroup) - * - * remove the property group from the current service. - * but only if it actually exists. - */ -int -smb_smf_delete_service_pgroup(smb_scfhandle_t *handle, char *pgroup) -{ - int ret = SMBD_SMF_OK; - int err; - - if (handle == NULL) { - return (SMBD_SMF_SYSTEM_ERR); - } - - /* - * only create a handle if it doesn't exist. It is ok to exist - * since the pg handle will be set as a side effect. - */ - if (handle->scf_pg == NULL) - handle->scf_pg = scf_pg_create(handle->scf_handle); - - /* - * only delete if it does exist. - */ - if (scf_service_get_pg(handle->scf_service, - pgroup, handle->scf_pg) == 0) { - /* does exist so delete it */ - if (scf_pg_delete(handle->scf_pg) != 0) { - ret = SMBD_SMF_SYSTEM_ERR; - err = scf_error(); - if (err != SCF_ERROR_NONE) { - smb_smf_scf_log_error("SMF delpg " - "problem: %s\n"); - } - } - } else { - err = scf_error(); - if (err != SCF_ERROR_NONE) - smb_smf_scf_log_error("SMF getpg problem: %s\n"); - ret = SMBD_SMF_SYSTEM_ERR; - } - if (ret == SMBD_SMF_SYSTEM_ERR && - scf_error() == SCF_ERROR_PERMISSION_DENIED) { - ret = SMBD_SMF_NO_PERMISSION; - } - return (ret); -} - -/* - * smb_smf_delete_instance_pgroup(handle, pgroup) - * - * remove the property group from the current instance. - * but only if it actually exists. - */ -int -smb_smf_delete_instance_pgroup(smb_scfhandle_t *handle, char *pgroup) -{ - int ret = SMBD_SMF_OK; - int err; - - if (handle == NULL) - return (SMBD_SMF_SYSTEM_ERR); - - /* - * only create a handle if it doesn't exist. It is ok to exist - * since the pg handle will be set as a side effect. - */ - if (handle->scf_pg == NULL) - handle->scf_pg = scf_pg_create(handle->scf_handle); - - /* - * only delete if it does exist. - */ - if (scf_instance_get_pg(handle->scf_instance, - pgroup, handle->scf_pg) == 0) { - /* does exist so delete it */ - if (scf_pg_delete(handle->scf_pg) != 0) { - ret = SMBD_SMF_SYSTEM_ERR; - err = scf_error(); - if (err != SCF_ERROR_NONE) { - smb_smf_scf_log_error("SMF delpg " - "problem: %s\n"); - } - } - } else { - err = scf_error(); - if (err != SCF_ERROR_NONE) - smb_smf_scf_log_error("SMF getpg problem: %s\n"); - ret = SMBD_SMF_SYSTEM_ERR; - } - if (ret == SMBD_SMF_SYSTEM_ERR && - scf_error() == SCF_ERROR_PERMISSION_DENIED) - ret = SMBD_SMF_NO_PERMISSION; - - return (ret); -} - -/* * Start transaction on current pg in handle. * The pg could be service or instance level. * Must be called after pg handle is obtained @@ -413,49 +178,6 @@ smb_smf_end_transaction(smb_scfhandle_t *handle) } /* - * Deletes property in current pg - */ -int -smb_smf_delete_property(smb_scfhandle_t *handle, char *propname) -{ - int ret = SMBD_SMF_OK; - scf_transaction_entry_t *entry = NULL; - - if (handle == NULL) - return (SMBD_SMF_SYSTEM_ERR); - - /* - * properties must be set in transactions and don't take - * effect until the transaction has been ended/committed. - */ - entry = scf_entry_create(handle->scf_handle); - if (entry != NULL) { - if (scf_transaction_property_delete(handle->scf_trans, entry, - propname) != 0) { - ret = SMBD_SMF_SYSTEM_ERR; - } - } else { - ret = SMBD_SMF_SYSTEM_ERR; - } - if (ret == SMBD_SMF_SYSTEM_ERR) { - switch (scf_error()) { - case SCF_ERROR_PERMISSION_DENIED: - ret = SMBD_SMF_NO_PERMISSION; - break; - } - } - - /* - * cleanup if there were any errors that didn't leave these - * values where they would be cleaned up later. - */ - if ((ret != SMBD_SMF_OK) && (entry != NULL)) - scf_entry_destroy(entry); - - return (ret); -} - -/* * Sets string property in current pg */ int @@ -843,103 +565,6 @@ smb_smf_get_opaque_property(smb_scfhandle_t *handle, char *propname, } /* - * Get property based on property type. Returns string value of that - * property. Only SCF_TYPE_ASTRING, SCF_TYPE_INTEGER, SCF_TYPE_BOOLEAN - * supported. - */ -int -smb_smf_get_property(smb_scfhandle_t *handle, int proptype, char *propname, - char *valstr, size_t sz) -{ - int64_t valint = 0; - uint8_t valbool = 0; - int ret = SMBD_SMF_OK; - - switch (proptype) { - case SCF_TYPE_ASTRING: - ret = smb_smf_get_string_property(handle, propname, - valstr, sz); - break; - case SCF_TYPE_INTEGER: - if ((ret = smb_smf_get_integer_property(handle, propname, - &valint)) != 0) - return (ret); - (void) snprintf(valstr, sz, "%lld", valint); - break; - case SCF_TYPE_BOOLEAN: - if ((ret = smb_smf_get_boolean_property(handle, propname, - &valbool)) != 0) - return (ret); - (void) strlcpy(valstr, (valbool ? "true" : "false"), sz); - break; - default: - return (SMBD_SMF_SYSTEM_ERR); - } - return (ret); -} - -/* - * Set property based on property type. - * Only SCF_TYPE_ASTRING, SCF_TYPE_INTEGER, SCF_TYPE_BOOLEAN supported. - */ -int -smb_smf_set_property(smb_scfhandle_t *handle, int proptype, - char *propname, char *valstr) -{ - int64_t valint = 0; - uint8_t valbool = 0; - int ret = SMBD_SMF_OK; - - switch (proptype) { - case SCF_TYPE_ASTRING: - ret = smb_smf_set_string_property(handle, propname, - valstr); - break; - case SCF_TYPE_INTEGER: - valint = strtol(valstr, 0, 10); - ret = smb_smf_set_integer_property(handle, propname, - valint); - break; - case SCF_TYPE_BOOLEAN: - if (strcasecmp(valstr, "true") == 0) - valbool = 1; - ret = smb_smf_set_boolean_property(handle, propname, valbool); - break; - default: - return (SMBD_SMF_SYSTEM_ERR); - } - return (ret); -} - -/* - * Gets an instance iterator for the service specified. - */ -smb_scfhandle_t * -smb_smf_get_iterator(char *svc_name) -{ - smb_scfhandle_t *handle = NULL; - - handle = smb_smf_scf_init(svc_name); - if (!handle) - return (NULL); - - handle->scf_inst_iter = scf_iter_create(handle->scf_handle); - if (handle->scf_inst_iter) { - if (scf_iter_service_instances(handle->scf_inst_iter, - handle->scf_service) != 0) { - smb_smf_scf_fini(handle); - handle = NULL; - } else { - handle->scf_instance = NULL; - } - } else { - smb_smf_scf_fini(handle); - handle = NULL; - } - return (handle); -} - -/* * smb_smf_scf_init() * * must be called before using any of the SCF functions. diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_util.c b/usr/src/lib/smbsrv/libsmb/common/smb_util.c index bce8efee8e..b1c5c32653 100644 --- a/usr/src/lib/smbsrv/libsmb/common/smb_util.c +++ b/usr/src/lib/smbsrv/libsmb/common/smb_util.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -30,10 +30,10 @@ #include <string.h> #include <stdlib.h> #include <pthread.h> -#include <syslog.h> #include <sys/varargs.h> #include <sys/types.h> #include <smbsrv/string.h> +#include <smbsrv/libsmb.h> #define C2H(c) "0123456789ABCDEF"[(c)] #define H2C(c) (((c) >= '0' && (c) <= '9') ? ((c) - '0') : \ @@ -56,7 +56,7 @@ * */ void -hexdump_offset(unsigned char *buffer, int nbytes, unsigned long *start, int log) +hexdump_offset(unsigned char *buffer, int nbytes, unsigned long *start) { static char *hex = "0123456789ABCDEF"; int i, count; @@ -67,13 +67,8 @@ hexdump_offset(unsigned char *buffer, int nbytes, unsigned long *start, int log) char *ap = ascbuf; char *hp = hexbuf; - if ((p = buffer) == 0) { - if (log) - syslog(LOG_DEBUG, "hexdump: (null)"); - else - (void) printf("hexdump: (null)\n"); + if ((p = buffer) == NULL) return; - } offset = *start; @@ -83,12 +78,7 @@ hexdump_offset(unsigned char *buffer, int nbytes, unsigned long *start, int log) for (i = 0; i < nbytes; ++i) { if (i && (i % 16) == 0) { - if (log) - syslog(LOG_DEBUG, - "%06X %s %s", offset, hexbuf, ascbuf); - else - (void) printf("%06X %s %s\n", - offset, hexbuf, ascbuf); + smb_tracef("%06X %s %s", offset, hexbuf, ascbuf); ap = ascbuf; hp = hexbuf; count = 0; @@ -104,13 +94,7 @@ hexdump_offset(unsigned char *buffer, int nbytes, unsigned long *start, int log) } if (count) { - if (log) - syslog(LOG_DEBUG, - "%06X %-48s %s", offset, hexbuf, ascbuf); - else - (void) printf("%06X %-48s %s\n", - offset, hexbuf, ascbuf); - + smb_tracef("%06X %-48s %s", offset, hexbuf, ascbuf); offset += count; } @@ -122,7 +106,7 @@ hexdump(unsigned char *buffer, int nbytes) { unsigned long start = 0; - hexdump_offset(buffer, nbytes, &start, 1); + hexdump_offset(buffer, nbytes, &start); } /* @@ -213,8 +197,8 @@ trim_whitespace(char *buf) char *p = buf; char *q = buf; - if (buf == 0) - return (0); + if (buf == NULL) + return (NULL); while (*p && isspace(*p)) ++p; diff --git a/usr/src/lib/smbsrv/libsmb/i386/Makefile b/usr/src/lib/smbsrv/libsmb/i386/Makefile index 710c9eb3dd..7ac7d3d534 100644 --- a/usr/src/lib/smbsrv/libsmb/i386/Makefile +++ b/usr/src/lib/smbsrv/libsmb/i386/Makefile @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -27,6 +27,7 @@ include ../Makefile.com +LDLIBS += -lsqlite DYNFLAGS += -R/usr/lib/smbsrv install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT) diff --git a/usr/src/lib/smbsrv/libsmb/sparc/Makefile b/usr/src/lib/smbsrv/libsmb/sparc/Makefile index 710c9eb3dd..7ac7d3d534 100644 --- a/usr/src/lib/smbsrv/libsmb/sparc/Makefile +++ b/usr/src/lib/smbsrv/libsmb/sparc/Makefile @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -27,6 +27,7 @@ include ../Makefile.com +LDLIBS += -lsqlite DYNFLAGS += -R/usr/lib/smbsrv install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT) diff --git a/usr/src/lib/smbsrv/libsmb/sparcv9/Makefile b/usr/src/lib/smbsrv/libsmb/sparcv9/Makefile index b3c4916b0c..03c6ea5b61 100644 --- a/usr/src/lib/smbsrv/libsmb/sparcv9/Makefile +++ b/usr/src/lib/smbsrv/libsmb/sparcv9/Makefile @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" diff --git a/usr/src/lib/smbsrv/libsmbns/common/libsmbns.h b/usr/src/lib/smbsrv/libsmbns/common/libsmbns.h index 01de8f7f02..f7034dd64d 100644 --- a/usr/src/lib/smbsrv/libsmbns/common/libsmbns.h +++ b/usr/src/lib/smbsrv/libsmbns/common/libsmbns.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -74,6 +74,8 @@ typedef enum adjoin_status { } adjoin_status_t; /* ADS functions */ +extern void ads_init(void); +extern void ads_refresh(void); extern ADS_HANDLE *ads_open(void); extern void ads_close(ADS_HANDLE *); extern int ads_publish_share(ADS_HANDLE *, const char *, const char *, @@ -84,11 +86,12 @@ extern int ads_build_unc_name(char *, int, const char *, const char *); extern int ads_lookup_share(ADS_HANDLE *, const char *, const char *, char *); extern int ads_add_share(ADS_HANDLE *, const char *, const char *, const char *); -extern int ads_domain_change_notify_handler(char *); -extern adjoin_status_t ads_join(char *, char *, char *, int); +extern adjoin_status_t ads_join(char *, char *, char *, char *, int); extern char *adjoin_report_err(adjoin_status_t status); +extern int ads_domain_change_cleanup(char *); /* DYNDNS functions */ +extern int dns_msgid_init(void); extern int dyndns_update(void); extern int dyndns_clear_rev_zone(void); @@ -97,8 +100,8 @@ extern int smb_kinit(char *user, char *passwd); /* NETBIOS Functions */ -extern int msdcs_lookup_ads(void); -extern void smb_netbios_start(void); +extern int msdcs_lookup_ads(char *); +extern int smb_netbios_start(void); extern void smb_netbios_shutdown(void); extern void smb_netbios_name_reconfig(void); @@ -142,10 +145,7 @@ struct ip_alias { #define GATEWAY_FILE "/etc/defaultrouter" /* NIC Config functions */ -extern void smb_resolver_init(void); -extern void smb_resolver_close(void); extern int smb_get_nameservers(struct in_addr *, int); -extern uint16_t smb_get_next_resid(void); extern void smb_nic_lock(void); extern void smb_nic_unlock(void); extern int smb_nic_init(void); diff --git a/usr/src/lib/smbsrv/libsmbns/common/mapfile-vers b/usr/src/lib/smbsrv/libsmbns/common/mapfile-vers index 63cf1a8f5b..ed0fde1e08 100644 --- a/usr/src/lib/smbsrv/libsmbns/common/mapfile-vers +++ b/usr/src/lib/smbsrv/libsmbns/common/mapfile-vers @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -31,18 +31,20 @@ SUNWprivate { ads_add_share; ads_build_unc_name; ads_close; - ads_domain_change_notify_handler; + ads_domain_change_cleanup; + ads_init; ads_join; ads_lookup_share; ads_open; ads_publish_share; + ads_refresh; ads_remove_share; + dns_msgid_init; dyndns_clear_rev_zone; dyndns_update; msdcs_lookup_ads; smb_browser_config; smb_get_nameservers; - smb_get_next_resid; smb_kinit; smb_netbios_name_reconfig; smb_netbios_start; @@ -75,8 +77,6 @@ SUNWprivate { smb_nic_status; smb_nic_unlock; smb_nic_validate_ip_address; - smb_resolver_close; - smb_resolver_init; local: *; }; diff --git a/usr/src/lib/smbsrv/libsmbns/common/smbns_ads.c b/usr/src/lib/smbsrv/libsmbns/common/smbns_ads.c index 5ea03bbd41..b988026dd3 100644 --- a/usr/src/lib/smbsrv/libsmbns/common/smbns_ads.c +++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_ads.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -59,10 +59,14 @@ #define ADS_COMPUTERS_CN "Computers" #define ADS_COMPUTER_NUM_ATTR 7 #define ADS_SHARE_NUM_ATTR 3 +#define ADS_SITE_MAX MAXHOSTNAMELEN /* current ADS server to communicate with */ ADS_HOST_INFO *ads_host_info = NULL; -mutex_t ads_mtx; +mutex_t ads_host_mtx; +char ads_site[ADS_SITE_MAX]; +mutex_t ads_site_mtx; + /* * adjoin_errmsg @@ -88,7 +92,7 @@ static char *adjoin_errmsg[] = { "ADJOIN failed to refresh SMB service." }; -static ADS_HANDLE *ads_open_main(char *user, char *password); +static ADS_HANDLE *ads_open_main(char *domain, char *user, char *password); static int ads_bind(ADS_HANDLE *); static void ads_get_computer_dn(ADS_HANDLE *, char *, size_t); static char *ads_get_host_principal(char *fqhost); @@ -105,6 +109,39 @@ static krb5_kvno ads_lookup_computer_attr_kvno(ADS_HANDLE *ah); static int ads_gen_machine_passwd(char *machine_passwd, int bufsz); static ADS_HOST_INFO *ads_get_host_info(void); static void ads_set_host_info(ADS_HOST_INFO *host); +static void ads_free_host_info(void); + +/* + * ads_init + * + * Initializes the ads_site global variable. + */ +void +ads_init(void) +{ + (void) mutex_lock(&ads_site_mtx); + (void) smb_config_getstr(SMB_CI_ADS_SITE, ads_site, sizeof (ads_site)); + (void) mutex_unlock(&ads_site_mtx); +} + +/* + * ads_refresh + * + * If the ads_site has changed, clear the ads_host_info cache. + */ +void +ads_refresh(void) +{ + char new_site[ADS_SITE_MAX]; + + (void) smb_config_getstr(SMB_CI_ADS_SITE, new_site, sizeof (new_site)); + (void) mutex_lock(&ads_site_mtx); + if (strcasecmp(ads_site, new_site)) { + (void) strlcpy(ads_site, new_site, sizeof (ads_site)); + ads_free_host_info(); + } + (void) mutex_unlock(&ads_site_mtx); +} /* * ads_build_unc_name @@ -118,9 +155,9 @@ int ads_build_unc_name(char *unc_name, int maxlen, const char *hostname, const char *shareUNC) { - char my_domain[ADS_MAXBUFLEN]; + char my_domain[MAXHOSTNAMELEN]; - if (smb_getdomainname(my_domain, sizeof (my_domain)) != 0) + if (smb_getfqdomainname(my_domain, sizeof (my_domain)) != 0) return (-1); (void) snprintf(unc_name, maxlen, "\\\\%s.%s\\%s", @@ -301,10 +338,10 @@ ads_free_host_list(ADS_HOST_INFO *host_list, int count) static void ads_set_host_info(ADS_HOST_INFO *host) { - (void) mutex_lock(&ads_mtx); + (void) mutex_lock(&ads_host_mtx); if (!ads_host_info) ads_host_info = host; - (void) mutex_unlock(&ads_mtx); + (void) mutex_unlock(&ads_host_mtx); } /* @@ -316,9 +353,9 @@ ads_get_host_info(void) { ADS_HOST_INFO *host; - (void) mutex_lock(&ads_mtx); + (void) mutex_lock(&ads_host_mtx); host = ads_host_info; - (void) mutex_unlock(&ads_mtx); + (void) mutex_unlock(&ads_host_mtx); return (host); } /* @@ -355,14 +392,13 @@ ads_find_host(char *ns, char *domain, int *port, char *service, int *go_next) int s; uint16_t id, rid, data_len, eport; int ipaddr; - struct hostent *h; char buf[NS_PACKETSZ], buf2[NS_PACKETSZ]; char *bufptr, *str; int i, ret; int queryReq; uint16_t query_cnt, ans_cnt, namser_cnt, addit_cnt; int quest_type, quest_class; - int dns_ip, decode_ip; + int dns_ip; struct in_addr addr; uint16_t flags = 0; int force_recurs = 0; @@ -397,7 +433,7 @@ retry: (void) memset(buf, 0, NS_PACKETSZ); bufptr = buf; - id = smb_get_next_resid(); + id = dns_get_msgid(); if (dyndns_build_header(&bufptr, BUFLEN_UDP(bufptr, buf), id, queryReq, query_cnt, ans_cnt, namser_cnt, addit_cnt, flags) == -1) { (void) close(s); @@ -514,13 +550,7 @@ retry: } /* check additional section to get IP address of ads host */ - decode_ip = 1; - smb_config_rdlock(); - if (smb_config_getyorn(SMB_CI_ADS_IPLOOKUP) == 1) - decode_ip = 0; - smb_config_unlock(); - - if (decode_ip && (addit_cnt > 0)) { + if (addit_cnt > 0) { int j; ads_hosts_list2 = (ADS_HOST_INFO *) @@ -589,50 +619,8 @@ retry: return (ads_host); } ads_free_host_list(ads_hosts_list2, addit_cnt); - } else { - /* use DNS to get IP address of ads host */ - /* - * Shouldn't get here unless entries exist in - * DNS but DNS server did - * not put them in additional section of DNS reply packet. - */ - for (i = 0; i < ans_cnt; i++) { - h = gethostbyname(ads_hosts_list[i].name); - if (h == NULL) - continue; - if (h->h_addr == NULL) - continue; - (void) memcpy(&ads_hosts_list[i].ip_addr, - h->h_addr, sizeof (addr.s_addr)); - if (ads_ping(ads_hosts_list[i].ip_addr) == 0) { - ads_host = (ADS_HOST_INFO *) - malloc(sizeof (ADS_HOST_INFO)); - if (ads_host == NULL) { - ads_free_host_list(ads_hosts_list, - ans_cnt); - return (NULL); - } - bzero(ads_host, sizeof (ADS_HOST_INFO)); - ads_host->name = strdup(ads_hosts_list[i].name); - if (ads_host->name == NULL) { - ads_free_host_list(ads_hosts_list, - ans_cnt); - return (NULL); - } - ads_host->ip_addr = ads_hosts_list[i].ip_addr; - ads_host->port = ads_hosts_list[i].port; - *port = ads_host->port; - addr.s_addr = ads_host->ip_addr; - syslog(LOG_DEBUG, "smb_ads: Found ADS server" - " using DNS: %s (%s) port %d", - ads_host->name, inet_ntoa(addr), - ads_host->port); - ads_free_host_list(ads_hosts_list, ans_cnt); - ads_set_host_info(ads_host); - return (ads_host); - } - } } + syslog(LOG_ERR, "smb_ads: Can't get IP for " "ADS host or ADS host is down.\n"); ads_free_host_list(ads_hosts_list, ans_cnt); @@ -720,16 +708,16 @@ ads_convert_domain(char *s) * ads_free_host_info * Free the memory use by the global ads_host_info and set it to NULL. */ -void +static void ads_free_host_info(void) { - (void) mutex_lock(&ads_mtx); + (void) mutex_lock(&ads_host_mtx); if (ads_host_info) { free(ads_host_info->name); free(ads_host_info); ads_host_info = NULL; } - (void) mutex_unlock(&ads_mtx); + (void) mutex_unlock(&ads_host_mtx); } /* @@ -743,12 +731,15 @@ ads_free_host_info(void) ADS_HANDLE * ads_open(void) { - uint32_t mode = smb_get_security_mode(); + char domain[MAXHOSTNAMELEN]; - if (mode != SMB_SECMODE_DOMAIN) + if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN) return (NULL); - return (ads_open_main(NULL, NULL)); + if (smb_getfqdomainname(domain, MAXHOSTNAMELEN) != 0) + return (NULL); + + return (ads_open_main(domain, NULL, NULL)); } /* @@ -770,75 +761,54 @@ ads_open(void) * * The ads_bind() routine is also called before the ADS handle is returned. * Parameters: - * None + * domain - fully-qualified domain name + * user - the user account for whom the Kerberos TGT ticket and ADS + * service tickets are acquired. + * password - password of the specified user + * * Returns: * NULL : can't connect to ADS server or other errors * ADS_HANDLE* : handle to ADS server */ -ADS_HANDLE * -ads_open_main(char *user, char *password) +static ADS_HANDLE * +ads_open_main(char *domain, char *user, char *password) { ADS_HANDLE *ah; LDAP *ld; int version = 3, ads_port, find_ads_retry; - char domain[MAXHOSTNAMELEN]; - int enable; ADS_HOST_INFO *ads_host = NULL; struct in_addr addr; - char *site, *service = NULL, *site_service = NULL; - int service_sz; + char site[ADS_SITE_MAX]; + char service[MAXHOSTNAMELEN]; + char site_service[MAXHOSTNAMELEN]; struct in_addr ns_list[MAXNS]; int i, cnt, go_next; - if (smb_getdomainname(domain, MAXHOSTNAMELEN) != 0) - return (NULL); - - smb_config_rdlock(); - enable = smb_config_getyorn(SMB_CI_ADS_ENABLE); - if (!enable) { - smb_config_unlock(); - return (NULL); - } - site = smb_config_getstr(SMB_CI_ADS_SITE); - smb_config_unlock(); + (void) mutex_lock(&ads_site_mtx); + (void) strlcpy(site, ads_site, sizeof (site)); + (void) mutex_unlock(&ads_site_mtx); find_ads_retry = 0; find_ads_host: ads_host = ads_get_host_info(); if (!ads_host) { - if (site && *site != 0) { - service_sz = strlen("_ldap._tcp.._sites.dc._msdcs.") + - strlen(site) + strlen(domain) + 1; - site_service = (char *)malloc(service_sz); - if (site_service == NULL) { - syslog(LOG_ERR, "smb_ads: No ADS host found" - " malloc failed..."); - return (NULL); - } - (void) snprintf(site_service, service_sz, + if (*site != '\0') { + (void) snprintf(site_service, sizeof (site_service), "_ldap._tcp.%s._sites.dc._msdcs.%s", site, domain); + } else { + *site_service = '\0'; } - service_sz = strlen("_ldap._tcp.dc._msdcs.") + strlen(domain) - + 1; - service = (char *)malloc(service_sz); - if (service == NULL) { - syslog(LOG_ERR, "smb_ads: No ADS host found malloc" - " failed..."); - if (site_service != NULL) - (void) free(site_service); - return (NULL); - } - (void) snprintf(service, service_sz, "_ldap._tcp.dc._msdcs.%s", - domain); + (void) snprintf(service, sizeof (service), + "_ldap._tcp.dc._msdcs.%s", domain); cnt = smb_get_nameservers(ns_list, MAXNS); ads_host = NULL; go_next = 0; for (i = 0; i < cnt; i++) { - if (site_service != NULL) { + if (*site_service != '\0') { ads_host = ads_find_host(inet_ntoa(ns_list[i]), domain, &ads_port, site_service, &go_next); } @@ -853,11 +823,6 @@ find_ads_host: } } - if (site_service) - (void) free(site_service); - if (service) - (void) free(service); - if (ads_host == NULL) { syslog(LOG_ERR, "smb_ads: No ADS host found from " "configured nameservers"); @@ -1789,8 +1754,11 @@ ads_get_host_principals(char *fqhost, char *domain, char **princ, if (fqhost) { (void) strlcpy(hostname, fqhost, MAXHOSTNAMELEN); } else { - if (smb_getfqhostname(hostname, MAXHOSTNAMELEN) != 0) + if (smb_gethostname(hostname, MAXHOSTNAMELEN, 0) != 0) return (-1); + + (void) snprintf(hostname, MAXHOSTNAMELEN, "%s.%s", hostname, + domain); } if ((p = ads_get_host_principal(hostname)) == NULL) { @@ -1846,13 +1814,13 @@ ads_computer_op(ADS_HANDLE *ah, int op) char usrctl_buf[16]; int max; - if (smb_getfqhostname(fqhost, MAXHOSTNAMELEN) != 0) - return (-1); - - if (smb_gethostname(sam_acct, MAXHOSTNAMELEN, 0) != 0) + if (smb_gethostname(fqhost, MAXHOSTNAMELEN, 0) != 0) return (-1); + (void) strlcpy(sam_acct, fqhost, MAXHOSTNAMELEN + 1); (void) strlcat(sam_acct, "$", MAXHOSTNAMELEN + 1); + (void) snprintf(fqhost, MAXHOSTNAMELEN, "%s.%s", fqhost, + ah->domain); if (ads_get_host_principals(fqhost, ah->domain, &svc_principal, &user_principal) == -1) { @@ -2165,22 +2133,32 @@ ads_gen_machine_passwd(char *machine_passwd, int bufsz) } /* - * ads_domain_change_notify_handler + * ads_domain_change_cleanup * - * Clear the host info cache and remove the old keys from the keytab - * as the ads_domain property has changed. + * If we're attempting to join the system to a new domain, the keys for + * the host principal regarding the old domain should be removed from + * Kerberos keytab. Also, the ads_host_info cache should be cleared. * - * domain - is the old ADS domain name. + * newdom is fully-qualified domain name. It can be set to empty string + * if user attempts to switch to workgroup mode. */ int -ads_domain_change_notify_handler(char *domain) +ads_domain_change_cleanup(char *newdom) { + char origdom[MAXHOSTNAMELEN]; char *princ_r; krb5_context ctx = NULL; krb5_principal krb5princ; int rc; - if (ads_get_host_principals(NULL, domain, NULL, &princ_r) == -1) + if (smb_getfqdomainname(origdom, MAXHOSTNAMELEN)) + return (0); + + if (strcasecmp(origdom, newdom) == 0) + return (0); + + ads_free_host_info(); + if (ads_get_host_principals(NULL, origdom, NULL, &princ_r) == -1) return (-1); if (smb_krb5_ctx_init(&ctx) != 0) { @@ -2198,7 +2176,7 @@ ads_domain_change_notify_handler(char *domain) rc = smb_krb5_remove_keytab_entries(ctx, krb5princ, SMBNS_KRB5_KEYTAB); free(princ_r); smb_krb5_ctx_fini(ctx); - ads_free_host_info(); + return (rc); } @@ -2228,7 +2206,8 @@ ads_domain_change_notify_handler(char *domain) * principal after the domain join operation. */ adjoin_status_t -ads_join(char *user, char *usr_passwd, char *machine_passwd, int len) +ads_join(char *domain, char *user, char *usr_passwd, char *machine_passwd, + int len) { ADS_HANDLE *ah = NULL; krb5_context ctx = NULL; @@ -2250,7 +2229,7 @@ ads_join(char *user, char *usr_passwd, char *machine_passwd, int len) krb5_enctype enctypes[] = {ENCTYPE_DES_CBC_CRC, ENCTYPE_DES_CBC_MD5, ENCTYPE_ARCFOUR_HMAC, ENCTYPE_AES128_CTS_HMAC_SHA1_96}; - if ((ah = ads_open_main(user, usr_passwd)) == NULL) { + if ((ah = ads_open_main(domain, user, usr_passwd)) == NULL) { (void) smb_config_refresh(); return (ADJOIN_ERR_GET_HANDLE); } diff --git a/usr/src/lib/smbsrv/libsmbns/common/smbns_browser.c b/usr/src/lib/smbsrv/libsmbns/common/smbns_browser.c index 853d1ff814..7ab634fd4d 100644 --- a/usr/src/lib/smbsrv/libsmbns/common/smbns_browser.c +++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_browser.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -37,6 +37,7 @@ #include <sys/socket.h> #include <arpa/inet.h> +#include <smbsrv/libsmb.h> #include <smbsrv/libsmbns.h> #include <smbsrv/cifs.h> @@ -852,13 +853,9 @@ smb_browser_send_HostAnnouncement(int net, int32_t next_announcement, uint32_t type; char resource_domain[SMB_PI_MAX_DOMAIN]; - syslog(LOG_DEBUG, "smb_browse: send_HostAnnouncement(%d)", net); - - smb_config_rdlock(); - (void) strlcpy(resource_domain, - smb_config_getstr(SMB_CI_DOMAIN_NAME), SMB_PI_MAX_DOMAIN); + if (smb_getdomainname(resource_domain, SMB_PI_MAX_DOMAIN) != 0) + return; (void) utf8_strupr(resource_domain); - smb_config_unlock(); if (addr == 0) { /* Local master Browser */ @@ -1134,15 +1131,10 @@ smb_browser_config(void) int net; char resource_domain[SMB_PI_MAX_DOMAIN]; - syslog(LOG_DEBUG, "smb_browse: reconfigure"); - smb_browser_init(); - - smb_config_rdlock(); - (void) strlcpy(resource_domain, - smb_config_getstr(SMB_CI_DOMAIN_NAME), SMB_PI_MAX_DOMAIN); + if (smb_getdomainname(resource_domain, SMB_PI_MAX_DOMAIN) != 0) + return; (void) utf8_strupr(resource_domain); - smb_config_unlock(); /* domain<00> */ smb_init_name_struct((unsigned char *)resource_domain, 0x00, @@ -1201,11 +1193,7 @@ smb_browser_init() net_cfg_t cfg; (void) smb_gethostname(hostname, MAXHOSTNAMELEN, 1); - - smb_config_rdlock(); - (void) strlcpy(cmnt, smb_config_getstr(SMB_CI_SYS_CMNT), - sizeof (cmnt)); - smb_config_unlock(); + (void) smb_config_getstr(SMB_CI_SYS_CMNT, cmnt, sizeof (cmnt)); smb_nc_cnt = smb_nic_get_num(); for (i = 0; i < smb_nc_cnt; i++) { @@ -1281,12 +1269,10 @@ smb_browser_non_master_duties(int net) smb_browser_putnet(subnet); smb_browser_send_HostAnnouncement(net, interval, 0, 0x1D); + if (smb_getdomainname(resource_domain, SMB_PI_MAX_DOMAIN) != 0) + return; - smb_config_rdlock(); - (void) strlcpy(resource_domain, - smb_config_getstr(SMB_CI_DOMAIN_NAME), SMB_PI_MAX_DOMAIN); (void) utf8_strupr(resource_domain); - smb_config_unlock(); smb_init_name_struct((unsigned char *)resource_domain, 0x1D, 0, 0, 0, 0, 0, &name); diff --git a/usr/src/lib/smbsrv/libsmbns/common/smbns_dyndns.c b/usr/src/lib/smbsrv/libsmbns/common/smbns_dyndns.c index 094c1b4946..c0f870b2ad 100644 --- a/usr/src/lib/smbsrv/libsmbns/common/smbns_dyndns.c +++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_dyndns.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -52,16 +52,39 @@ #define DEL_NONE 2 /* Maximum retires if not authoritative */ #define MAX_AUTH_RETRIES 3 +/* Number of times to retry a DNS query */ +#define DYNDNS_MAX_QUERY_RETRIES 3 +/* Timeout value, in seconds, for DNS query responses */ +#define DYNDNS_QUERY_TIMEOUT 2 -static int -dyndns_enabled(void) +static uint16_t dns_msgid; +mutex_t dns_msgid_mtx; + +int +dns_msgid_init(void) { - int enabled; + struct __res_state res; + + bzero(&res, sizeof (struct __res_state)); + if (res_ninit(&res) < 0) + return (-1); - smb_config_rdlock(); - enabled = smb_config_getyorn(SMB_CI_DYNDNS_ENABLE); - smb_config_unlock(); - return (enabled); + (void) mutex_lock(&dns_msgid_mtx); + dns_msgid = res.id; + (void) mutex_unlock(&dns_msgid_mtx); + res_nclose(&res); + return (0); +} + +int +dns_get_msgid(void) +{ + uint16_t id; + + (void) mutex_lock(&dns_msgid_mtx); + id = ++dns_msgid; + (void) mutex_unlock(&dns_msgid_mtx); + return (id); } /* @@ -651,7 +674,7 @@ dyndns_build_tkey_msg(char *buf, char *key_name, uint16_t *id, (void) memset(buf, 0, MAX_TCP_SIZE); bufptr = buf; - *id = smb_get_next_resid(); + *id = dns_get_msgid(); /* add TCP length info that follows this field */ bufptr = dyndns_put_nshort(bufptr, @@ -931,7 +954,7 @@ dyndns_build_add_remove_msg(char *buf, int update_zone, const char *hostname, bufptr = buf; if (*id == 0) - *id = smb_get_next_resid(); + *id = dns_get_msgid(); if (dyndns_build_header(&bufptr, BUFLEN_UDP(bufptr, buf), *id, queryReq, zoneCount, preqCount, updateCount, additionalCount, 0) == -1) { @@ -1114,13 +1137,7 @@ dyndns_build_signed_tsig_msg(char *buf, int update_zone, const char *hostname, /* * dyndns_udp_send_recv - * This routine sends and receives UDP DNS request and reply messages. Time - * out value and retry count is indicated by two environment variables: - * lookup_dns_retry_cnt - * lookup_dns_retry_sec - * If either of these two variables are undefined or their value exceed the - * value of 10 then a default value of 3 retry and/or a default value of 3 - * secs are used. + * This routine sends and receives UDP DNS request and reply messages. * * Pre-condition: Caller must call dyndns_open_init_socket() before calling * this function. @@ -1137,34 +1154,15 @@ dyndns_build_signed_tsig_msg(char *buf, int update_zone, const char *hostname, int dyndns_udp_send_recv(int s, char *buf, int buf_sz, char *rec_buf) { - int i, retval, addr_len, max_retries; + int i, retval, addr_len; struct timeval tv, timeout; fd_set rfds; struct sockaddr_in from_addr; - char *p; - - smb_config_rdlock(); - p = smb_config_getstr(SMB_CI_DYNDNS_RETRY_COUNT); - if (p == NULL || *p == 0) { - max_retries = 3; - } else { - max_retries = atoi(p); - if (max_retries < 1 || max_retries > 10) - max_retries = 3; - } - p = smb_config_getstr(SMB_CI_DYNDNS_RETRY_SEC); timeout.tv_usec = 0; - if (p == NULL || *p == 0) { - timeout.tv_sec = 3; - } else { - timeout.tv_sec = atoi(p); - if (timeout.tv_sec < 1 || timeout.tv_sec > 10) - timeout.tv_sec = 3; - } - smb_config_unlock(); + timeout.tv_sec = DYNDNS_QUERY_TIMEOUT; - for (i = 0; i < max_retries + 1; i++) { + for (i = 0; i <= DYNDNS_MAX_QUERY_RETRIES; i++) { if (send(s, buf, buf_sz, 0) == -1) { syslog(LOG_ERR, "dyndns: UDP send error (%s)\n", strerror(errno)); @@ -1193,7 +1191,8 @@ dyndns_udp_send_recv(int s, char *buf, int buf_sz, char *rec_buf) } } - if (i == (max_retries + 1)) { /* did not receive anything */ + /* did not receive anything */ + if (i == (DYNDNS_MAX_QUERY_RETRIES + 1)) { syslog(LOG_ERR, "dyndns: max retries for UDP recv reached\n"); return (-1); } @@ -1506,7 +1505,7 @@ retry_higher: return (-1); } - if (smb_get_security_mode() == SMB_SECMODE_DOMAIN) + if (smb_config_get_secmode() == SMB_SECMODE_DOMAIN) ret = dyndns_sec_add_remove_entry(update_zone, hostname, ip_addr, life_time, update_type, del_type, dns_str); @@ -1679,7 +1678,7 @@ dyndns_update(void) struct in_addr addr; int rc; - if (!dyndns_enabled()) + if (!smb_config_getbool(SMB_CI_DYNDNS_ENABLE)) return (-1); if (smb_getfqhostname(fqdn, MAXHOSTNAMELEN) != 0) @@ -1760,7 +1759,7 @@ dyndns_clear_rev_zone(void) struct in_addr addr; int rc; - if (!dyndns_enabled()) + if (!smb_config_getbool(SMB_CI_DYNDNS_ENABLE)) return (-1); if (smb_getfqhostname(fqdn, MAXHOSTNAMELEN) != 0) diff --git a/usr/src/lib/smbsrv/libsmbns/common/smbns_dyndns.h b/usr/src/lib/smbsrv/libsmbns/common/smbns_dyndns.h index 7140eb4d59..42f69751cc 100644 --- a/usr/src/lib/smbsrv/libsmbns/common/smbns_dyndns.h +++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_dyndns.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -182,6 +182,7 @@ extern "C" { #define BUFLEN_TCP(x, y) (MAX_TCP_SIZE-(x-y)) #define BUFLEN_UDP(x, y) (NS_PACKETSZ-(x-y)) +extern int dns_get_msgid(void); extern char *dyndns_get_nshort(char *, uint16_t *); extern char *dyndns_get_int(char *, int *); extern int dyndns_build_header(char **, int, uint16_t, int, diff --git a/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios.c b/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios.c index 7b165e3b44..4f8340dcca 100644 --- a/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios.c +++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -73,8 +73,8 @@ smb_netbios_shutdown(void) nb_status.state = NETBIOS_SHUT_DOWN; } -void -smb_netbios_start() +int +smb_netbios_start(void) { int rc; mutex_t *mp; @@ -84,13 +84,12 @@ smb_netbios_start() rc = pthread_create(&smb_nbns_thr, 0, smb_netbios_name_service_daemon, 0); if (rc) - return; + return (-1); mp = &nb_status.mtx; cvp = &nb_status.cv; (void) mutex_lock(mp); - while (!(nb_status.state & (NETBIOS_NAME_SVC_RUNNING | NETBIOS_NAME_SVC_FAILED))) { (void) cond_wait(cvp, mp); @@ -98,71 +97,62 @@ smb_netbios_start() if (nb_status.state & NETBIOS_NAME_SVC_FAILED) { (void) mutex_unlock(mp); - (void) fprintf(stderr, - "smbd: Netbios Name service startup failed!"); smb_netbios_shutdown(); - return; + return (-1); } (void) mutex_unlock(mp); - (void) fprintf(stderr, "smbd: Netbios Name service started."); smb_netbios_name_config(); /* Startup Netbios datagram service; port 138 */ rc = pthread_create(&smb_nbds_thr, 0, smb_netbios_datagram_service_daemon, 0); - if (rc == 0) { - (void) mutex_lock(mp); - while (!(nb_status.state & (NETBIOS_DATAGRAM_SVC_RUNNING | - NETBIOS_DATAGRAM_SVC_FAILED))) { - (void) cond_wait(cvp, mp); - } + if (rc != 0) { + smb_netbios_shutdown(); + return (-1); + } - if (nb_status.state & NETBIOS_DATAGRAM_SVC_FAILED) { - (void) mutex_unlock(mp); - (void) fprintf(stderr, "smbd: Netbios Datagram service " - "startup failed!"); - smb_netbios_shutdown(); - return; - } + (void) mutex_lock(mp); + while (!(nb_status.state & (NETBIOS_DATAGRAM_SVC_RUNNING | + NETBIOS_DATAGRAM_SVC_FAILED))) { + (void) cond_wait(cvp, mp); + } + + if (nb_status.state & NETBIOS_DATAGRAM_SVC_FAILED) { (void) mutex_unlock(mp); - } else { smb_netbios_shutdown(); - return; + return (-1); } - - (void) fprintf(stderr, "smbd: Netbios Datagram service started."); + (void) mutex_unlock(mp); /* Startup Netbios browser service */ rc = pthread_create(&smb_nbbs_thr, 0, smb_browser_daemon, 0); if (rc) { smb_netbios_shutdown(); - return; + return (-1); } - (void) fprintf(stderr, "smbd: Netbios Browser client started."); - /* Startup Our internal, 1 second resolution, timer */ rc = pthread_create(&smb_nbts_thr, 0, smb_netbios_timer, 0); - if (rc == 0) { - (void) mutex_lock(mp); - while (!(nb_status.state & (NETBIOS_TIMER_RUNNING | - NETBIOS_TIMER_FAILED))) { - (void) cond_wait(cvp, mp); - } + if (rc != 0) { + smb_netbios_shutdown(); + return (-1); + } - if (nb_status.state & NETBIOS_TIMER_FAILED) { - (void) mutex_unlock(mp); - smb_netbios_shutdown(); - return; - } + (void) mutex_lock(mp); + while (!(nb_status.state & (NETBIOS_TIMER_RUNNING | + NETBIOS_TIMER_FAILED))) { + (void) cond_wait(cvp, mp); + } + + if (nb_status.state & NETBIOS_TIMER_FAILED) { (void) mutex_unlock(mp); - } else { smb_netbios_shutdown(); - return; + return (-1); } + (void) mutex_unlock(mp); - (void) fprintf(stderr, "smbd: Netbios Timer service started."); + return (0); } /*ARGSUSED*/ @@ -253,10 +243,8 @@ smb_encode_netbios_name(unsigned char *name, char suffix, unsigned char *scope, dest->name[NETBIOS_NAME_SZ - 1] = suffix; if (scope == NULL) { - smb_config_rdlock(); - (void) strlcpy((char *)dest->scope, - smb_config_getstr(SMB_CI_NBSCOPE), NETBIOS_DOMAIN_NAME_MAX); - smb_config_unlock(); + (void) smb_config_getstr(SMB_CI_NBSCOPE, (char *)dest->scope, + NETBIOS_DOMAIN_NAME_MAX); } else { (void) strlcpy((char *)dest->scope, (const char *)scope, NETBIOS_DOMAIN_NAME_MAX); diff --git a/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_cache.c b/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_cache.c index 1e47658700..a1c3bb2c03 100644 --- a/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_cache.c +++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_cache.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -111,11 +111,9 @@ smb_netbios_cache_lookup(struct name_entry *name) if (NETBIOS_NAME_IS_STAR(name->name)) { /* Return our address */ - smb_config_rdlock(); - (void) strlcpy((char *)scope, - smb_config_getstr(SMB_CI_NBSCOPE), sizeof (scope)); + (void) smb_config_getstr(SMB_CI_NBSCOPE, (char *)scope, + sizeof (scope)); (void) utf8_strupr((char *)scope); - smb_config_unlock(); if (smb_getnetbiosname((char *)hostname, MAXHOSTNAMELEN) != 0) return (NULL); diff --git a/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_name.c b/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_name.c index b8de94a504..f7794479ab 100644 --- a/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_name.c +++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_name.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -2126,7 +2126,8 @@ static int smb_send_node_status_response(struct addr_entry *addr, struct name_packet *original_packet) { - uint32_t net_ipaddr, max_connections; + uint32_t net_ipaddr; + int64_t max_connections; struct arpreq arpreq; struct name_packet packet; struct resource_record answer; @@ -2166,9 +2167,8 @@ smb_send_node_status_response(struct addr_entry *addr, else net_ipaddr = cfg.ip; - smb_config_rdlock(); - max_connections = smb_config_getnum(SMB_CI_MAX_CONNECTIONS); - smb_config_unlock(); + (void) smb_config_getnum(SMB_CI_MAX_CONNECTIONS, &max_connections); + while (!scan_done) { if ((scan + 6) >= scan_end) { packet.info |= NAME_NM_FLAGS_TC; @@ -4489,10 +4489,6 @@ smb_netbios_wins_config(char *ip) { uint32_t ipaddr; - /* Return if ip == NULL since this is the same as "" */ - if (ip == NULL) - return; - ipaddr = inet_addr(ip); if (ipaddr != INADDR_NONE) { smb_nbns[nbns_num].flags = ADDR_FLAG_VALID; @@ -4511,9 +4507,10 @@ smb_netbios_name_config(void) uint32_t ipaddr; struct name_entry name; char myname[MAXHOSTNAMELEN]; - int i; + int i; int smb_nc_cnt; net_cfg_t cfg; + char wins_ip[16]; if (smb_getnetbiosname(myname, MAXHOSTNAMELEN) != 0) return; @@ -4544,10 +4541,10 @@ smb_netbios_name_config(void) bzero(smb_nbns, sizeof (addr_entry_t) * SMB_PI_MAX_WINS); /* add any configured WINS */ - smb_config_rdlock(); - smb_netbios_wins_config(smb_config_getstr(SMB_CI_WINS_SRV1)); - smb_netbios_wins_config(smb_config_getstr(SMB_CI_WINS_SRV2)); - smb_config_unlock(); + (void) smb_config_getstr(SMB_CI_WINS_SRV1, wins_ip, sizeof (wins_ip)); + smb_netbios_wins_config(wins_ip); + (void) smb_config_getstr(SMB_CI_WINS_SRV2, wins_ip, sizeof (wins_ip)); + smb_netbios_wins_config(wins_ip); for (i = 0; i < smb_nc_cnt; i++) { if (smb_nic_get_byind(i, &cfg) == NULL) { diff --git a/usr/src/lib/smbsrv/libsmbns/common/smbns_netlogon.c b/usr/src/lib/smbsrv/libsmbns/common/smbns_netlogon.c index d74bcb168d..2631bd0f68 100644 --- a/usr/src/lib/smbsrv/libsmbns/common/smbns_netlogon.c +++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_netlogon.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -478,27 +478,22 @@ smb_netlogon_rdc_rsp(char *src_name, uint32_t src_ipaddr) uint32_t prefer_ipaddr = 0; char ipstr[16]; char srcip[16]; - char *p; int rc; (void) inet_ntop(AF_INET, (const void *)(&src_ipaddr), srcip, sizeof (srcip)); - smb_config_rdlock(); - if ((p = smb_config_get(SMB_CI_DOMAIN_SRV)) != 0) { - rc = inet_pton(AF_INET, p, &prefer_ipaddr); + rc = smb_config_getstr(SMB_CI_DOMAIN_SRV, ipstr, sizeof (ipstr)); + if (rc == SMBD_SMF_OK) { + rc = inet_pton(AF_INET, ipstr, &prefer_ipaddr); if (rc == 0) prefer_ipaddr = 0; if (!initialized) { - (void) inet_ntop(AF_INET, - (const void *)(&prefer_ipaddr), - ipstr, sizeof (ipstr)); syslog(LOG_DEBUG, "SMB DC Preference: %s", ipstr); initialized = 1; } } - smb_config_unlock(); syslog(LOG_DEBUG, "DC Offer [%s]: %s [%s]", resource_domain, src_name, srcip); @@ -553,49 +548,35 @@ better_dc(uint32_t cur_ip, uint32_t new_ip) * best way. The IP address isn't set up in the ADS_HANDLE so we need to * make the ads_find_host call. This will only succeed if ADS is enabled. * + * Parameter: + * nbt_domain - NETBIOS name of the domain + * * Returns 1 if a domain controller was found and its name and IP address * have been updated. Otherwise returns 0. */ int -msdcs_lookup_ads(void) +msdcs_lookup_ads(char *nbt_domain) { ADS_HOST_INFO *hinfo = 0; int ads_port = 0; char ads_domain[MAXHOSTNAMELEN]; char site_service[MAXHOSTNAMELEN]; char service[MAXHOSTNAMELEN]; - char *site; + char site[MAXHOSTNAMELEN]; char *p; char *ip_addr; struct in_addr ns_list[MAXNS]; int i, cnt, go_next; - if (smb_getdomainname(ads_domain, MAXHOSTNAMELEN) != 0) + if (!nbt_domain) return (0); - /* - * Initialize the NT domain name. - */ - (void) strlcpy(resource_domain, ads_domain, SMB_PI_MAX_DOMAIN); - if ((p = strchr(resource_domain, '.')) != 0) - *p = '\0'; - - smb_config_rdlock(); - if (smb_config_getyorn(SMB_CI_MSDCS_DISABLE) != 0) { - /* - * The system administrator doesn't - * want to use ADS to find the PDC. - */ - syslog(LOG_DEBUG, "msdcsLookupADS: disabled"); - smb_config_unlock(); + (void) strlcpy(resource_domain, nbt_domain, SMB_PI_MAX_DOMAIN); + if (smb_resolve_fqdn(nbt_domain, ads_domain, MAXHOSTNAMELEN) != 1) return (0); - } - site = smb_config_getstr(SMB_CI_ADS_SITE); - smb_config_unlock(); - syslog(LOG_DEBUG, "msdcsLookupADS %s, MAXHOSTNAMELEN=%d", - ads_domain, MAXHOSTNAMELEN); - if (site && *site != 0) { + (void) smb_config_getstr(SMB_CI_ADS_SITE, site, sizeof (site)); + if (*site != '\0') { (void) snprintf(site_service, MAXHOSTNAMELEN, "_ldap._tcp.%s._sites.dc._msdcs.%s", site, ads_domain); diff --git a/usr/src/lib/smbsrv/libsmbns/common/smbns_nicconfig.c b/usr/src/lib/smbsrv/libsmbns/common/smbns_nicconfig.c index 6adeca1d50..2316bd595f 100644 --- a/usr/src/lib/smbsrv/libsmbns/common/smbns_nicconfig.c +++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_nicconfig.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -57,41 +57,22 @@ static void smb_nic_clear_if_list(struct if_list *); /* This is the list we will monitor */ static net_cfg_list_t smb_nic_list = { NULL, 0 }; static pthread_mutex_t smb_nic_mutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_mutex_t smb_ns_mutex = PTHREAD_MUTEX_INITIALIZER; - -/* Nameserver information */ -static struct __res_state smb_res; - -void -smb_resolver_init(void) -{ - int ret; - (void) pthread_mutex_lock(&smb_ns_mutex); - ret = res_ninit(&smb_res); - (void) pthread_mutex_unlock(&smb_ns_mutex); - if (ret < 0) { - syslog(LOG_ERR, "Failed to initialize resolver lib"); - } -} - -void -smb_resolver_close(void) -{ - (void) pthread_mutex_lock(&smb_ns_mutex); - res_nclose(&smb_res); - (void) pthread_mutex_unlock(&smb_ns_mutex); -} int smb_get_nameservers(struct in_addr *ips, int sz) { union res_sockaddr_union set[MAXNS]; int i, cnt; + struct __res_state res_state; if (ips == NULL) return (0); - (void) pthread_mutex_lock(&smb_ns_mutex); - cnt = res_getservers(&smb_res, set, MAXNS); + + bzero(&res_state, sizeof (struct __res_state)); + if (res_ninit(&res_state) < 0) + return (0); + + cnt = res_getservers(&res_state, set, MAXNS); for (i = 0; i < cnt; i++) { if (i >= sz) break; @@ -100,20 +81,10 @@ smb_get_nameservers(struct in_addr *ips, int sz) inet_ntoa(ips[i])); } syslog(LOG_DEBUG, "NS Found %d name servers\n", i); - (void) pthread_mutex_unlock(&smb_ns_mutex); + res_nclose(&res_state); return (i); } -uint16_t -smb_get_next_resid(void) -{ - uint16_t id; - (void) pthread_mutex_lock(&smb_ns_mutex); - id = ++smb_res.id; - (void) pthread_mutex_unlock(&smb_ns_mutex); - return (id); -} - /* * The common NIC library will provide functions to obtain information * on all interfaces. Information will include IP addresses, netmasks @@ -651,7 +622,6 @@ smb_nic_build_network_structures(net_cfg_t **nc, int *number) char excludestr[MAX_EXCLUDE_LIST_LEN]; ipaddr_t exclude[SMB_PI_MAX_NETWORKS]; int nexclude; - char *winsexclude; *number = 0; numnics = smb_nic_build_if_name(&names); @@ -662,12 +632,8 @@ smb_nic_build_network_structures(net_cfg_t **nc, int *number) } bzero(nc_array, sizeof (net_cfg_t) * numnics); - smb_config_rdlock(); - excludestr[0] = '\0'; - winsexclude = smb_config_getstr(SMB_CI_WINS_EXCL); - if (winsexclude != NULL) - (void) strlcpy(excludestr, winsexclude, sizeof (excludestr)); - smb_config_unlock(); + (void) smb_config_getstr(SMB_CI_WINS_EXCL, excludestr, + sizeof (excludestr)); nexclude = smb_wins_iplist(excludestr, exclude, SMB_PI_MAX_NETWORKS); for (i = 0; i < numnics; i++) { diff --git a/usr/src/lib/smbsrv/libsmbrdr/common/libsmbrdr.h b/usr/src/lib/smbsrv/libsmbrdr/common/libsmbrdr.h index 8d537650ac..3c450da186 100644 --- a/usr/src/lib/smbsrv/libsmbrdr/common/libsmbrdr.h +++ b/usr/src/lib/smbsrv/libsmbrdr/common/libsmbrdr.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -52,7 +52,7 @@ extern unsigned char *smbrdr_ipc_get_passwd(void); /* Redirector LOGON function */ extern int mlsvc_logon(char *, char *, char *); -extern int smbrdr_rpc_readx(int, char *, int); +extern int smbrdr_readx(int, char *, int); /* Redirector rpcpipe functions */ @@ -62,14 +62,12 @@ extern int mlsvc_close_pipe(int); /* Redirector session functions */ extern void smbrdr_init(void); -extern int mlsvc_locate_domain_controller(char *); extern int mlsvc_session_native_values(int, int *, int *, int *); -extern void mlsvc_check_sessions(void); extern int mlsvc_echo(char *); extern void mlsvc_disconnect(char *); -extern int smbrdr_rpc_transact(int, char *, int, char *, int); +extern int smbrdr_transact(int, char *, int, char *, int); /* DEBUG functions */ diff --git a/usr/src/lib/smbsrv/libsmbrdr/common/mapfile-vers b/usr/src/lib/smbsrv/libsmbrdr/common/mapfile-vers index b6902203ef..ffa2d56871 100644 --- a/usr/src/lib/smbsrv/libsmbrdr/common/mapfile-vers +++ b/usr/src/lib/smbsrv/libsmbrdr/common/mapfile-vers @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -27,12 +27,9 @@ SUNWprivate { global: - mlsvc_check_sessions; mlsvc_close_pipe; mlsvc_disconnect; mlsvc_echo; - mlsvc_install_pdc_cb; - mlsvc_locate_domain_controller; mlsvc_logon; mlsvc_open_pipe; mlsvc_session_native_values; @@ -47,8 +44,8 @@ SUNWprivate { smbrdr_ipc_set; smbrdr_ipc_skip_lsa_query; smbrdr_ipc_get_passwd; - smbrdr_rpc_readx; - smbrdr_rpc_transact; + smbrdr_readx; + smbrdr_transact; local: *; }; diff --git a/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr.h b/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr.h index 35db51adc6..5275708b72 100644 --- a/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr.h +++ b/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -117,16 +117,16 @@ struct sdb_session { char native_lanman[SMB_PI_MAX_LANMAN]; int sock; short port; - unsigned short secmode; + uint16_t secmode; uint32_t sesskey; uint32_t challenge_len; - unsigned char challenge_key[32]; - unsigned char smb_flags; - unsigned short smb_flags2; - unsigned short vc; + uint8_t challenge_key[32]; + uint8_t smb_flags; + uint16_t smb_flags2; + uint16_t vc; uint32_t remote_caps; - unsigned short state; - unsigned int sid; /* session id */ + uint8_t state; + uint32_t sid; /* session id */ int remote_os; int remote_lm; int pdc_type; @@ -208,12 +208,12 @@ void smbrdr_session_unlock(struct sdb_session *); /* * smbrdr_logon.c */ -int smbrdr_smb_logoff(struct sdb_logon *); +int smbrdr_logoffx(struct sdb_logon *); /* smbrdr_netuse.c */ void smbrdr_netuse_logoff(unsigned short); struct sdb_netuse *smbrdr_netuse_get(int); -unsigned short mlsvc_tree_connect(char *, char *, char *); +unsigned short smbrdr_tree_connect(char *, char *, char *); int smbrdr_tree_disconnect(unsigned short); void smbrdr_netuse_put(struct sdb_netuse *); @@ -232,8 +232,8 @@ DWORD smbrdr_rcv(smbrdr_handle_t *, int); DWORD smbrdr_exchange(smbrdr_handle_t *, smb_hdr_t *, long); void smbrdr_handle_free(smbrdr_handle_t *); int smbrdr_sign_init(struct sdb_session *, struct sdb_logon *); -int smbrdr_sign_fini(struct sdb_session *); -int smbrdr_sign_unset_key(struct sdb_session *); +void smbrdr_sign_fini(struct sdb_session *); +void smbrdr_sign_unset_key(struct sdb_session *); void smbrdr_lock_transport(void); void smbrdr_unlock_transport(void); diff --git a/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_ipc_util.c b/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_ipc_util.c index cbce43db5e..8185ddee5e 100644 --- a/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_ipc_util.c +++ b/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_ipc_util.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -34,11 +34,9 @@ #include <string.h> #include <strings.h> -#include <syslog.h> #include <synch.h> #include <smbsrv/libsmbrdr.h> - #include <smbsrv/mlsvc.h> #include <smbsrv/smbinfo.h> #include <smbrdr.h> @@ -53,20 +51,17 @@ static smbrdr_ipc_t orig_ipc_info; static int smbrdr_get_machine_pwd_hash(unsigned char *hash) { - char *pwd; + char pwd[SMB_PI_MAX_PASSWD]; int rc = 0; - smb_config_rdlock(); - pwd = smb_config_getstr(SMB_CI_MACHINE_PASSWD); - if (!pwd || *pwd == 0) { - smb_config_unlock(); + rc = smb_config_getstr(SMB_CI_MACHINE_PASSWD, pwd, sizeof (pwd)); + if ((rc != SMBD_SMF_OK) || *pwd == '\0') { return (-1); } - if (smb_auth_ntlm_hash((char *)pwd, hash) != 0) + if (smb_auth_ntlm_hash(pwd, hash) != 0) rc = -1; - smb_config_unlock(); return (rc); } diff --git a/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_lib.c b/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_lib.c index ac4743548c..432d66141e 100644 --- a/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_lib.c +++ b/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_lib.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -36,17 +36,12 @@ #include <smbsrv/ntstatus.h> #include <smbrdr.h> -static DWORD smbrdr_handle_setup(smbrdr_handle_t *srh, unsigned char cmd, - struct sdb_session *session, struct sdb_logon *logon, - struct sdb_netuse *netuse); - -static int smbrdr_hdr_setup(smbrdr_handle_t *srh); - -static DWORD smbrdr_hdr_process(smbrdr_handle_t *srh, smb_hdr_t *smb_hdr); - -static int smbrdr_sign(smb_sign_ctx_t *sign_ctx, smb_msgbuf_t *mb); -static int smbrdr_sign_chk(smb_sign_ctx_t *sign_ctx, smb_msgbuf_t *mb, - unsigned char *signature); +static DWORD smbrdr_handle_setup(smbrdr_handle_t *, unsigned char, + struct sdb_session *, struct sdb_logon *, struct sdb_netuse *); +static int smbrdr_hdr_setup(smbrdr_handle_t *); +static DWORD smbrdr_hdr_process(smbrdr_handle_t *, smb_hdr_t *); +static int smbrdr_sign(smb_sign_ctx_t *, smb_msgbuf_t *); +static int smbrdr_sign_chk(smb_sign_ctx_t *, smb_msgbuf_t *, unsigned char *); void smbrdr_lock_transport() { nb_lock(); } void smbrdr_unlock_transport() { nb_unlock(); } @@ -73,13 +68,10 @@ smbrdr_request_init(smbrdr_handle_t *srh, DWORD status; status = smbrdr_handle_setup(srh, cmd, session, logon, netuse); - if (status != NT_STATUS_SUCCESS) { - syslog(LOG_DEBUG, "Smbrdr[%d]: initialization failed", cmd); + if (status != NT_STATUS_SUCCESS) return (status); - } if (smbrdr_hdr_setup(srh) < SMB_HEADER_LEN) { - syslog(LOG_DEBUG, "Smbrdr[%d]: cannot setup header", cmd); smbrdr_handle_free(srh); return (NT_STATUS_INTERNAL_ERROR); } @@ -105,8 +97,11 @@ smbrdr_send(smbrdr_handle_t *srh) int rc; if (smbrdr_sign(&srh->srh_session->sign_ctx, &srh->srh_mbuf) != - SMBAUTH_SUCCESS) + SMBAUTH_SUCCESS) { + syslog(LOG_DEBUG, "smbrdr_send[%d]: signing failed", + srh->srh_cmd); return (NT_STATUS_INTERNAL_ERROR); + } rc = nb_send(srh->srh_session->sock, srh->srh_buf, smb_msgbuf_used(&srh->srh_mbuf)); @@ -163,7 +158,6 @@ smbrdr_rcv(smbrdr_handle_t *srh, int is_first_rsp) return (NT_STATUS_UNEXPECTED_NETWORK_ERROR); } - /* initialize for processing response */ smb_msgbuf_init(&srh->srh_mbuf, srh->srh_buf, rc, srh->srh_mbflags); status = smbrdr_hdr_process(srh, &smb_hdr); @@ -177,7 +171,7 @@ smbrdr_rcv(smbrdr_handle_t *srh, int is_first_rsp) if (!smbrdr_sign_chk(sign_ctx, &srh->srh_mbuf, smb_hdr.extra.extra.security_sig)) { - syslog(LOG_ERR, "SmbrdrExchange[%d]: bad signature", + syslog(LOG_DEBUG, "smbrdr_rcv[%d]: bad signature", srh->srh_cmd); return (NT_STATUS_INVALID_NETWORK_RESPONSE); } @@ -217,15 +211,18 @@ smbrdr_exchange(smbrdr_handle_t *srh, smb_hdr_t *smb_hdr, long timeout) mb = &srh->srh_mbuf; sign_ctx = &srh->srh_session->sign_ctx; - if (smbrdr_sign(sign_ctx, mb) != SMBAUTH_SUCCESS) + if (smbrdr_sign(sign_ctx, mb) != SMBAUTH_SUCCESS) { + syslog(LOG_DEBUG, "smbrdr_exchange[%d]: signing failed", + srh->srh_cmd); return (NT_STATUS_INTERNAL_ERROR); + } rc = nb_exchange(srh->srh_session->sock, srh->srh_buf, smb_msgbuf_used(mb), srh->srh_buf, SMBRDR_REQ_BUFSZ, timeout); if (rc < 0) { - syslog(LOG_ERR, "SmbrdrExchange[%d]: failed (%d)", + syslog(LOG_DEBUG, "smbrdr_exchange[%d]: failed (%d)", srh->srh_cmd, rc); if (srh->srh_cmd != SMB_COM_ECHO) { @@ -251,7 +248,7 @@ smbrdr_exchange(smbrdr_handle_t *srh, smb_hdr_t *smb_hdr, long timeout) /* Signature validation */ if (!smbrdr_sign_chk(sign_ctx, mb, smb_hdr->extra.extra.security_sig)) { - syslog(LOG_ERR, "SmbrdrExchange[%d]: bad signature", + syslog(LOG_DEBUG, "smbrdr_exchange[%d]: bad signature", srh->srh_cmd); return (NT_STATUS_INVALID_NETWORK_RESPONSE); } @@ -313,14 +310,12 @@ smbrdr_sign_init(struct sdb_session *session, struct sdb_logon *logon) if ((sign_ctx->ssc_flags & SMB_SCF_REQUIRED) && !(sign_ctx->ssc_flags & SMB_SCF_STARTED) && (logon->type != SDB_LOGON_ANONYMOUS)) { - if (smb_mac_init(sign_ctx, &logon->auth) != SMBAUTH_SUCCESS) { - syslog(LOG_DEBUG, "SmbrdrSignInit: mac_init failed"); + if (smb_mac_init(sign_ctx, &logon->auth) != SMBAUTH_SUCCESS) return (-1); - } + sign_ctx->ssc_flags |= (SMB_SCF_STARTED | SMB_SCF_KEY_ISSET_THIS_LOGON); session->smb_flags2 |= SMB_FLAGS2_SMB_SECURITY_SIGNATURE; - syslog(LOG_DEBUG, "SmbrdrSignInit: mac key is set"); rc = 1; } @@ -333,23 +328,16 @@ smbrdr_sign_init(struct sdb_session *session, struct sdb_logon *logon) * Invalidate the MAC key if the first non-anonymous/non-guest user logon * fail. */ -int +void smbrdr_sign_fini(struct sdb_session *session) { - smb_sign_ctx_t *sign_ctx; - int rc = 0; - - sign_ctx = &session->sign_ctx; + smb_sign_ctx_t *sign_ctx = &session->sign_ctx; if (sign_ctx->ssc_flags & SMB_SCF_KEY_ISSET_THIS_LOGON) { sign_ctx->ssc_flags &= ~SMB_SCF_STARTED; sign_ctx->ssc_flags &= ~SMB_SCF_KEY_ISSET_THIS_LOGON; sign_ctx->ssc_seqnum = 0; - syslog(LOG_DEBUG, "SmbrdrSignFini: packet signing stopped"); - rc = 1; } - - return (rc); } /* @@ -359,21 +347,12 @@ smbrdr_sign_fini(struct sdb_session *session) * SmbSessionSetupAndX request for the first non-anonymous/non-guest * logon. */ -int +void smbrdr_sign_unset_key(struct sdb_session *session) { - smb_sign_ctx_t *sign_ctx; - int rc = 0; - - sign_ctx = &session->sign_ctx; - - if (sign_ctx->ssc_flags & SMB_SCF_KEY_ISSET_THIS_LOGON) { - sign_ctx->ssc_flags &= ~SMB_SCF_KEY_ISSET_THIS_LOGON; - syslog(LOG_DEBUG, "SmbrdrSignUnsetKey: unset KEY_ISSET flag"); - rc = 1; - } + smb_sign_ctx_t *sign_ctx = &session->sign_ctx; - return (rc); + sign_ctx->ssc_flags &= ~SMB_SCF_KEY_ISSET_THIS_LOGON; } /* @@ -396,10 +375,9 @@ smbrdr_handle_setup(smbrdr_handle_t *srh, struct sdb_netuse *netuse) { srh->srh_buf = (unsigned char *)malloc(SMBRDR_REQ_BUFSZ); - if (srh->srh_buf == 0) { - syslog(LOG_ERR, "Smbrdr[%d]: resource shortage", cmd); + if (srh->srh_buf == NULL) return (NT_STATUS_NO_MEMORY); - } + bzero(srh->srh_buf, SMBRDR_REQ_BUFSZ); srh->srh_mbflags = (session->remote_caps & CAP_UNICODE) @@ -468,6 +446,10 @@ smb_decode_nt_hdr(smb_msgbuf_t *mb, smb_hdr_t *hdr) * Assuming 'srh->srh_mbuf' contains a response from a Windows client, * decodes the 32 bytes SMB header. * + * Buffer overflow typically means that the server has more data than + * it could fit in the response buffer. The client can use subsequent + * SmbReadX requests to obtain the remaining data (KB 193839). + * * Returns: * * NT_STATUS_INVALID_NETWORK_RESPONSE error decoding the header @@ -480,43 +462,26 @@ smbrdr_hdr_process(smbrdr_handle_t *srh, smb_hdr_t *smb_hdr) { int rc; - /* - * Returns the number of decoded bytes on success - * or some negative MSGBUF_XXX error code on failure - */ rc = smb_decode_nt_hdr(&srh->srh_mbuf, smb_hdr); - if (rc < SMB_HEADER_LEN) { - syslog(LOG_ERR, "Smbrdr[%d]: bad SMB header (%d)", + syslog(LOG_DEBUG, "smbrdr[%d]: invalid header (%d)", srh->srh_cmd, rc); return (NT_STATUS_INVALID_NETWORK_RESPONSE); } - if (smb_hdr->status.ntstatus != 0) { - /* - * MSDN article: 193839 - * "The buffer overflow status is usually returned by a Windows - * server to inform the client that there is more data in its - * buffer than it could put in the packet. - * - * The buffer overflow should not be considered as an error. - * Subsequent SmbReadX request is required to obtain the - * remaining data in the server's buffer. - */ - if (NT_SC_VALUE(smb_hdr->status.ntstatus) - == NT_STATUS_BUFFER_OVERFLOW) { - syslog(LOG_DEBUG, "Smbrdr[%d]: %s", srh->srh_cmd, - xlate_nt_status(smb_hdr->status.ntstatus)); - } else { - syslog(LOG_ERR, "Smbrdr[%d]: request failed (%s)", - srh->srh_cmd, - xlate_nt_status(smb_hdr->status.ntstatus)); - return (smb_hdr->status.ntstatus); - } + switch (NT_SC_VALUE(smb_hdr->status.ntstatus)) { + case NT_STATUS_SUCCESS: + case NT_STATUS_BUFFER_OVERFLOW: + break; + + default: + syslog(LOG_DEBUG, "smbrdr[%d]: request failed (%s)", + srh->srh_cmd, xlate_nt_status(smb_hdr->status.ntstatus)); + return (smb_hdr->status.ntstatus); } if (smb_hdr->command != srh->srh_cmd) { - syslog(LOG_ERR, "Smbrdr[%d]: reply mismatch (%d)", + syslog(LOG_DEBUG, "smbrdr[%d]: reply mismatch (%d)", srh->srh_cmd, smb_hdr->command); return (NT_STATUS_REPLY_MESSAGE_MISMATCH); } @@ -551,8 +516,7 @@ smbrdr_sign(smb_sign_ctx_t *sign_ctx, smb_msgbuf_t *mb) { if (sign_ctx->ssc_flags & SMB_SCF_STARTED) { if (sign_ctx->ssc_seqnum % 2) { - syslog(LOG_DEBUG, "SmbrdrSign: even sequence number" - " is expected(%d)", + syslog(LOG_DEBUG, "smbrdr_sign: invalid sequence (%d)", sign_ctx->ssc_seqnum); } if (smb_mac_sign(sign_ctx, smb_msgbuf_base(mb), diff --git a/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_logon.c b/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_logon.c index d33f253b29..374afe8c6f 100644 --- a/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_logon.c +++ b/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_logon.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -34,6 +34,7 @@ #include <strings.h> #include <syslog.h> #include <synch.h> +#include <sys/errno.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> @@ -44,10 +45,10 @@ #include <smbrdr_ipc_util.h> #include <smbrdr.h> -static int mlsvc_anonymous_logon(char *domain_controller, char *domain_name); -static int mlsvc_auth_logon(char *domain_controller, char *domain_name, - char *username, unsigned char *pwd_hash); -static int smbrdr_smb_session_setupandx(struct sdb_logon *logon); +static int smbrdr_anonymous_logon(char *domain_controller, char *domain_name); +static int smbrdr_auth_logon(char *domain_controller, char *domain_name, + char *username); +static int smbrdr_session_setupx(struct sdb_logon *logon); static boolean_t smbrdr_logon_validate(char *server, char *username); static struct sdb_logon *smbrdr_logon_init(struct sdb_session *session, char *username, unsigned char *pwd); @@ -58,7 +59,7 @@ static int smbrdr_authenticate(char *primary_domain, char *account_name, /* * mlsvc_logon * - * If the username is NULL, an anonymous session will be established. + * If the username is MLSVC_ANON_USER, an anonymous session will be established. * Otherwise, an authenticated session will be established based on the * specified credentials. */ @@ -66,48 +67,39 @@ int mlsvc_logon(char *domain_controller, char *domain, char *username) { int rc; - unsigned char *pwd_hash = NULL; - if (username) { - pwd_hash = smbrdr_ipc_get_passwd(); - rc = mlsvc_auth_logon(domain_controller, domain, username, - pwd_hash); - } else { - rc = mlsvc_anonymous_logon(domain_controller, domain); - } + if (strcmp(username, MLSVC_ANON_USER) == 0) + rc = smbrdr_anonymous_logon(domain_controller, domain); + else + rc = smbrdr_auth_logon(domain_controller, domain, username); return (rc); } /* - * mlsvc_anonymous_logon + * smbrdr_anonymous_logon * * Set up an anonymous session. If the session to the resource domain * controller appears to be okay we shouldn't need to do anything here. * Otherwise we clean up the stale session and create a new one. */ static int -mlsvc_anonymous_logon(char *domain_controller, char *domain_name) +smbrdr_anonymous_logon(char *domain_controller, char *domain_name) { - int rc = 0; - if (smbrdr_logon_validate(domain_controller, MLSVC_ANON_USER)) - /* session & user are good use them */ return (0); - if (smbrdr_negotiate(domain_name) != 0) { - syslog(LOG_ERR, "smbrdr: (anon logon) negotiate <%s> failed", - (domain_name ? domain_name : "NoName")); + syslog(LOG_DEBUG, "smbrdr_anonymous_logon: negotiate failed"); return (-1); } if (smbrdr_logon_user(domain_controller, MLSVC_ANON_USER, 0) < 0) { - syslog(LOG_ERR, "smbrdr: (anon logon) logon failed"); - rc = -1; + syslog(LOG_DEBUG, "smbrdr_anonymous_logon: logon failed"); + return (-1); } - return (rc); + return (0); } int @@ -131,7 +123,7 @@ mlsvc_user_getauth(char *domain_controller, char *username, } /* - * mlsvc_auth_logon + * smbrdr_auth_logon * * Set up a user session. If the session to the resource domain controller * appears to be okay we shouldn't need to do anything here. Otherwise we @@ -140,18 +132,19 @@ mlsvc_user_getauth(char *domain_controller, char *username, * due to an inactivity timeout or a domain controller reset. */ static int -mlsvc_auth_logon(char *domain_controller, char *domain_name, char *username, - unsigned char *pwd_hash) +smbrdr_auth_logon(char *domain_controller, char *domain_name, char *username) { int erc; + unsigned char *pwd_hash = NULL; if (username == NULL || *username == 0) { - syslog(LOG_ERR, "smbrdr: auth logon (no username)"); + syslog(LOG_DEBUG, "smbrdr_auth_logon: no username"); return (-1); } + pwd_hash = smbrdr_ipc_get_passwd(); if (!pwd_hash || *pwd_hash == 0) { - syslog(LOG_ERR, "smbrdr: auth logon (no password)"); + syslog(LOG_DEBUG, "smbrdr_auth_logon: no password"); return (-1); } @@ -159,7 +152,7 @@ mlsvc_auth_logon(char *domain_controller, char *domain_name, char *username, return (0); if (smbrdr_negotiate(domain_name) != 0) { - syslog(LOG_ERR, "smbrdr: admin logon (negotiate failed)"); + syslog(LOG_DEBUG, "smbrdr_auth_logon: negotiate failed"); return (-1); } @@ -189,7 +182,7 @@ smbrdr_authenticate(char *primary_domain, char *account_name, if ((di = smb_getdomaininfo(0)) == 0) { - syslog(LOG_ERR, "MlsvcAuthenticate[%s]: %s", account_name, + syslog(LOG_DEBUG, "smbrdr_authenticate[%s]: %s", account_name, xlate_nt_status(NT_STATUS_CANT_ACCESS_DOMAIN_INFO)); return (-1); } @@ -211,7 +204,7 @@ smbrdr_authenticate(char *primary_domain, char *account_name, * to the resource domain. */ if (strcasecmp(di->domain, primary_domain)) { - syslog(LOG_ERR, "MlsvcAuthenticate: %s\\%s: not account domain", + syslog(LOG_DEBUG, "smbrdr_authenticate: %s\\%s: invalid domain", primary_domain, account_name); return (-2); } @@ -225,9 +218,9 @@ smbrdr_authenticate(char *primary_domain, char *account_name, * This is the entry point for logging a user onto the domain. The * session structure should have been obtained via a successful call * to smbrdr_smb_connect. We allocate a logon structure to hold the - * user details and attempt to logon using smbrdr_smb_session_setupandx. Note - * that we expect the password fields to have been encrypted before - * this call. + * user details and attempt to logon using smbrdr_session_setupx. + * Note that we expect the password fields to have been encrypted + * before this call. * * On success, the logon structure will be returned. Otherwise a null * pointer will be returned. @@ -245,8 +238,8 @@ smbrdr_logon_user(char *server, char *username, unsigned char *pwd) } session = smbrdr_session_lock(server, 0, SDB_SLCK_WRITE); - if (session == 0) { - syslog(LOG_ERR, "smbrdr: (logon[%s]) no session with %s", + if (session == NULL) { + syslog(LOG_DEBUG, "smbrdr_logon_user: %s: no session with %s", username, server); return (-1); } @@ -267,14 +260,14 @@ smbrdr_logon_user(char *server, char *username, unsigned char *pwd) logon = smbrdr_logon_init(session, username, pwd); - if (logon == 0) { - syslog(LOG_ERR, "smbrdr: (logon[%s]) resource shortage", - username); + if (logon == NULL) { + syslog(LOG_DEBUG, "smbrdr_logon_user: %s: %s", + username, strerror(ENOMEM)); smbrdr_session_unlock(session); return (-1); } - if (smbrdr_smb_session_setupandx(logon) < 0) { + if (smbrdr_session_setupx(logon) < 0) { free(logon); smbrdr_session_unlock(session); return (-1); @@ -284,7 +277,7 @@ smbrdr_logon_user(char *server, char *username, unsigned char *pwd) free(logon); if (old_logon.type != SDB_LOGON_NONE) { - (void) smbrdr_smb_logoff(&old_logon); + (void) smbrdr_logoffx(&old_logon); } smbrdr_session_unlock(session); @@ -294,7 +287,7 @@ smbrdr_logon_user(char *server, char *username, unsigned char *pwd) /* - * smbrdr_smb_session_setupandx + * smbrdr_session_setupx * * Build and send an SMB session setup command. This is used to log a * user onto the domain. See CIFS section 4.1.2. @@ -302,7 +295,7 @@ smbrdr_logon_user(char *server, char *username, unsigned char *pwd) * Returns 0 on success. Otherwise returns a -ve error code. */ static int -smbrdr_smb_session_setupandx(struct sdb_logon *logon) +smbrdr_session_setupx(struct sdb_logon *logon) { struct sdb_session *session; smb_hdr_t smb_hdr; @@ -322,10 +315,8 @@ smbrdr_smb_session_setupandx(struct sdb_logon *logon) * Paranoia check - we should never get this * far without a valid session structure. */ - if ((session = logon->session) == 0) { - syslog(LOG_ERR, "smbrdr_smb_session_setupandx: no data"); + if ((session = logon->session) == NULL) return (-1); - } if (session->remote_caps & CAP_UNICODE) { strlen_fn = mts_wcequiv_strlen; @@ -336,15 +327,18 @@ smbrdr_smb_session_setupandx(struct sdb_logon *logon) null_size = sizeof (char); } - if (smbrdr_sign_init(session, logon) < 0) + if (smbrdr_sign_init(session, logon) < 0) { + syslog(LOG_DEBUG, + "smbrdr_session_setupx: smbrdr_sign_init failed"); return (-1); + } status = smbrdr_request_init(&srh, SMB_COM_SESSION_SETUP_ANDX, session, 0, 0); if (status != NT_STATUS_SUCCESS) { - (void) smbrdr_sign_fini(session); - syslog(LOG_ERR, "SmbrdrSessionSetup: %s", + smbrdr_sign_fini(session); + syslog(LOG_DEBUG, "smbrdr_session_setupx: %s", xlate_nt_status(status)); return (-1); } @@ -415,18 +409,18 @@ smbrdr_smb_session_setupandx(struct sdb_logon *logon) } if (rc <= 0) { - syslog(LOG_ERR, "smbrdr_smb_session_setupandx: encode failed"); + syslog(LOG_DEBUG, "smbrdr_session_setupx: encode failed"); smbrdr_handle_free(&srh); - (void) smbrdr_sign_fini(session); + smbrdr_sign_fini(session); return (-1); } status = smbrdr_exchange(&srh, &smb_hdr, 0); if (status != NT_STATUS_SUCCESS) { - syslog(LOG_ERR, "SmbrdrSessionSetup: %s", + syslog(LOG_DEBUG, "smbrdr_session_setupx: %s", xlate_nt_status(status)); smbrdr_handle_free(&srh); - (void) smbrdr_sign_fini(session); + smbrdr_sign_fini(session); return (-1); } @@ -461,9 +455,9 @@ smbrdr_smb_session_setupandx(struct sdb_logon *logon) } if (rc <= 0) { - syslog(LOG_ERR, "RdrSessionSetup: decode failed"); + syslog(LOG_DEBUG, "smbrdr_session_setupx: decode failed"); smbrdr_handle_free(&srh); - (void) smbrdr_sign_fini(session); + smbrdr_sign_fini(session); return (-1); } @@ -476,7 +470,7 @@ smbrdr_smb_session_setupandx(struct sdb_logon *logon) logon->type = SDB_LOGON_GUEST; smbrdr_handle_free(&srh); - (void) smbrdr_sign_unset_key(session); + smbrdr_sign_unset_key(session); logon->state = SDB_LSTATE_SETUP; @@ -484,7 +478,7 @@ smbrdr_smb_session_setupandx(struct sdb_logon *logon) } /* - * smbrdr_smb_logoff + * smbrdr_logoffx * * Build and send an SMB session logoff (SMB_COM_LOGOFF_ANDX) command. * This is the inverse of an SMB_COM_SESSION_SETUP_ANDX. See CIFS @@ -494,7 +488,7 @@ smbrdr_smb_session_setupandx(struct sdb_logon *logon) * Returns 0 on success. Otherwise returns a -ve error code. */ int -smbrdr_smb_logoff(struct sdb_logon *logon) +smbrdr_logoffx(struct sdb_logon *logon) { struct sdb_session *session; smbrdr_handle_t srh; @@ -527,7 +521,7 @@ smbrdr_smb_logoff(struct sdb_logon *logon) if (status != NT_STATUS_SUCCESS) { logon->state = SDB_LSTATE_SETUP; - syslog(LOG_ERR, "smbrdr: logoff %s (%s)", logon->username, + syslog(LOG_DEBUG, "smbrdr_logoffx: %s: %s", logon->username, xlate_nt_status(status)); return (-1); } @@ -536,14 +530,14 @@ smbrdr_smb_logoff(struct sdb_logon *logon) if (rc < 0) { logon->state = SDB_LSTATE_SETUP; smbrdr_handle_free(&srh); - syslog(LOG_ERR, "smbrdr: logoff %s (encode failed)", + syslog(LOG_DEBUG, "smbrdr_logoffx: %s: encode failed", logon->username); return (rc); } status = smbrdr_exchange(&srh, &smb_hdr, 0); if (status != NT_STATUS_SUCCESS) { - syslog(LOG_ERR, "smbrdr: logoff %s (%s)", logon->username, + syslog(LOG_DEBUG, "smbrdr_logoffx: %s: %s", logon->username, xlate_nt_status(status)); rc = -1; } else { @@ -570,7 +564,7 @@ smbrdr_logon_init(struct sdb_session *session, char *username, unsigned char *pwd) { struct sdb_logon *logon; - int smbrdr_lmcompl; + int64_t smbrdr_lmcompl; int rc; logon = (struct sdb_logon *)malloc(sizeof (sdb_logon_t)); @@ -580,9 +574,7 @@ smbrdr_logon_init(struct sdb_session *session, char *username, bzero(logon, sizeof (struct sdb_logon)); logon->session = session; - smb_config_rdlock(); - smbrdr_lmcompl = smb_config_getnum(SMB_CI_LM_LEVEL); - smb_config_unlock(); + (void) smb_config_getnum(SMB_CI_LM_LEVEL, &smbrdr_lmcompl); if (strcmp(username, "IPC$") == 0) { logon->type = SDB_LOGON_ANONYMOUS; @@ -625,7 +617,8 @@ smbrdr_logon_validate(char *server, char *username) valid = B_TRUE; } else { session->state = SDB_SSTATE_STALE; - syslog(LOG_DEBUG, "smbrdr: (logon) stale session"); + syslog(LOG_DEBUG, + "smbrdr_logon_validate: stale session"); } smbrdr_session_unlock(session); diff --git a/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_netbios.c b/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_netbios.c index 2066dab051..756a816378 100644 --- a/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_netbios.c +++ b/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_netbios.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -41,7 +41,6 @@ #include <string.h> #include <unistd.h> -#include <syslog.h> #include <synch.h> #include <sys/types.h> #include <sys/uio.h> @@ -128,8 +127,6 @@ nb_keep_alive(int fd) (void) mutex_lock(&nb_mutex); rc = nb_write_msg(fd, (unsigned char *)¬hing, 0, SESSION_KEEP_ALIVE); - if (rc < 0) - syslog(LOG_ERR, "nb_keep_alive: write failed"); (void) mutex_unlock(&nb_mutex); return (rc); @@ -145,9 +142,7 @@ nb_send(int fd, unsigned char *send_buf, unsigned send_cnt) { int rc; - if ((rc = nb_write_msg(fd, send_buf, send_cnt, SESSION_MESSAGE)) < 0) - syslog(LOG_ERR, "nb_send: write failed: rc=%d", rc); - + rc = nb_write_msg(fd, send_buf, send_cnt, SESSION_MESSAGE); return (rc); } @@ -166,16 +161,12 @@ nb_rcv(int fd, unsigned char *recv_buf, unsigned recv_max, long timeout) do { rc = nb_read_msg(fd, recv_buf, recv_max, &type, timeout); - if (rc < 0) { - syslog(LOG_ERR, "nb_rcv: read failed: rc=%d", rc); + if (rc < 0) return (rc); - } } while (type == SESSION_KEEP_ALIVE); - if (type != SESSION_MESSAGE) { - syslog(LOG_ERR, "nb_rcv: invalid type: %d", type); + if (type != SESSION_MESSAGE) return (NB_RCV_MSG_ERR_INVTYPE); - } return (rc); } @@ -236,8 +227,6 @@ nb_session_request(int fd, char *called_name, char *called_scope, rc = nb_write_msg(fd, (unsigned char *)sr_buf, len, SESSION_REQUEST); if (rc < 0) { - syslog(LOG_ERR, "nb_session_request: write failed:" - " rc=%d", rc); (void) mutex_unlock(&nb_mutex); return (rc); } @@ -287,7 +276,6 @@ nb_write_msg(int fd, unsigned char *buf, unsigned count, int type) /* * We should never see descriptor 0 (stdin). */ - syslog(LOG_ERR, "nb_write_msg: invalid descriptor (%d)", fd); return (-1); } @@ -310,7 +298,6 @@ nb_write_msg(int fd, unsigned char *buf, unsigned count, int type) rc = writev(fd, iov, 2); if (rc != 4 + count) { - syslog(LOG_ERR, "nb_write_msg: writev rc=%d", rc); return (-3); /* error */ } @@ -340,7 +327,6 @@ nb_read_msg(int fd, unsigned char *buf, unsigned max_buf, /* * We should never see descriptor 0 (stdin). */ - syslog(LOG_ERR, "nb_write_msg: invalid descriptor (%d)", fd); return (NB_READ_MSG_ERR); } @@ -350,7 +336,6 @@ nb_read_msg(int fd, unsigned char *buf, unsigned max_buf, tval.tv_usec = 0; if ((rc = select(fd + 1, &readfds, 0, 0, &tval)) <= 0) { - syslog(LOG_ERR, "nb_read_msg: select: %d", rc); return (NB_READ_MSG_ERR); } diff --git a/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_netuse.c b/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_netuse.c index 508b258cd6..2cb74e66e8 100644 --- a/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_netuse.c +++ b/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_netuse.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -31,6 +31,7 @@ * Specification (December 19, 1997). */ +#include <sys/errno.h> #include <string.h> #include <strings.h> #include <syslog.h> @@ -38,7 +39,6 @@ #include <pthread.h> #include <smbsrv/libsmbrdr.h> - #include <smbrdr.h> #include <smbsrv/ntstatus.h> @@ -48,12 +48,12 @@ */ static struct sdb_netuse netuse_table[N_NETUSE_TABLE]; -static int smbrdr_smb_tcon(struct sdb_session *session, +static int smbrdr_tree_connectx(struct sdb_session *session, struct sdb_netuse *netuse, char *path, int path_len); static struct sdb_netuse *smbrdr_netuse_alloc(struct sdb_session *session, char *sharename); -static int smbrdr_smb_tdcon(struct sdb_netuse *netuse); +static int smbrdr_tdcon(struct sdb_netuse *netuse); static void smbrdr_netuse_clear(struct sdb_netuse *netuse) @@ -69,19 +69,19 @@ smbrdr_netuse_free(struct sdb_netuse *netuse) } /* - * mlsvc_tree_connect + * smbrdr_tree_connect * * Establish a share (tree connect). We need to retrieve the session * for the specified host and allocate a netuse structure. We set up * the path here (UNC encoded) to make handling the malloc/free easier - * and pass everything on to smbrdr_smb_tcon where, if everything goes well, - * a valid tid will be stored in the netuse structure. + * and pass everything on to smbrdr_tree_connectx where. If everything + * goes well, a valid tid will be stored in the netuse structure. * * On success, a pointer to the netuse is returned. Otherwise the * netuse is cleared and a null pointer is returned. */ unsigned short -mlsvc_tree_connect(char *hostname, char *username, char *sharename) +smbrdr_tree_connect(char *hostname, char *username, char *sharename) { struct sdb_session *session; struct sdb_netuse *netuse; @@ -92,15 +92,15 @@ mlsvc_tree_connect(char *hostname, char *username, char *sharename) * Make sure there is a session & logon for given info */ session = smbrdr_session_lock(hostname, username, SDB_SLCK_READ); - if (session == 0) { - syslog(LOG_ERR, "smbrdr: (tcon) no session for %s@%s", + if (session == NULL) { + syslog(LOG_DEBUG, "smbrdr_tree_connect: no session for %s@%s", username, hostname); return (0); } if ((netuse = smbrdr_netuse_alloc(session, sharename)) == 0) { - syslog(LOG_ERR, "smbrdr: (tcon) init failed"); + syslog(LOG_DEBUG, "smbrdr_tree_connect: init failed"); smbrdr_session_unlock(session); return (0); } @@ -114,7 +114,7 @@ mlsvc_tree_connect(char *hostname, char *username, char *sharename) if ((path = (char *)malloc(path_len)) == 0) { smbrdr_netuse_free(netuse); smbrdr_session_unlock(session); - syslog(LOG_ERR, "smbrdr: (tcon) resource shortage"); + syslog(LOG_DEBUG, "smbrdr_tree_connect: %s", strerror(ENOMEM)); return (0); } @@ -125,11 +125,11 @@ mlsvc_tree_connect(char *hostname, char *username, char *sharename) else path_len = strlen(path); - if (smbrdr_smb_tcon(session, netuse, path, path_len) < 0) { + if (smbrdr_tree_connectx(session, netuse, path, path_len) < 0) { smbrdr_netuse_free(netuse); smbrdr_session_unlock(session); free(path); - syslog(LOG_ERR, "smbrdr: (tcon) failed connecting to %s", path); + syslog(LOG_DEBUG, "smbrdr_tree_connect: %s failed", path); return (0); } @@ -141,7 +141,7 @@ mlsvc_tree_connect(char *hostname, char *username, char *sharename) /* - * smbrdr_smb_tcon + * smbrdr_tree_connectx * * This message requests a share (tree connect) request to the server * associated with the session. The password is not relevant here if @@ -151,7 +151,7 @@ mlsvc_tree_connect(char *hostname, char *username, char *sharename) * Returns 0 on success. Otherwise returns a -ve error code. */ static int -smbrdr_smb_tcon(struct sdb_session *session, struct sdb_netuse *netuse, +smbrdr_tree_connectx(struct sdb_session *session, struct sdb_netuse *netuse, char *path, int path_len) { smb_hdr_t smb_hdr; @@ -170,7 +170,8 @@ smbrdr_smb_tcon(struct sdb_session *session, struct sdb_netuse *netuse, session, &session->logon, 0); if (status != NT_STATUS_SUCCESS) { - syslog(LOG_ERR, "SmbrdrTcon: %s", xlate_nt_status(status)); + syslog(LOG_DEBUG, "smbrdr_tree_connectx: %s", + xlate_nt_status(status)); return (-1); } @@ -202,26 +203,25 @@ smbrdr_smb_tcon(struct sdb_session *session, struct sdb_netuse *netuse, service); /* Service */ if (rc <= 0) { - syslog(LOG_ERR, "smbrdr_smb_tcon: encode failed"); + syslog(LOG_DEBUG, "smbrdr_tree_connectx: encode failed"); smbrdr_handle_free(&srh); return (-1); } status = smbrdr_exchange(&srh, &smb_hdr, 0); if (status != NT_STATUS_SUCCESS) { - syslog(LOG_ERR, "SmbrdrTcon: %s", xlate_nt_status(status)); - rc = -1; - } else { - rc = 0; + syslog(LOG_DEBUG, "smbrdr_tree_connectx: %s", + xlate_nt_status(status)); + smbrdr_handle_free(&srh); + return (-1); } netuse->tid = smb_hdr.tid; netuse->state = SDB_NSTATE_CONNECTED; smbrdr_handle_free(&srh); - return (rc); + return (0); } - /* * smbrdr_netuse_logoff * @@ -242,7 +242,7 @@ smbrdr_netuse_logoff(unsigned short uid) netuse = &netuse_table[i]; (void) mutex_lock(&netuse->mtx); if (netuse->uid == uid) - (void) smbrdr_smb_tdcon(netuse); + (void) smbrdr_tdcon(netuse); (void) mutex_unlock(&netuse->mtx); } } @@ -255,7 +255,7 @@ smbrdr_tree_disconnect(unsigned short tid) netuse = smbrdr_netuse_get(tid); if (netuse) { - (void) smbrdr_smb_tdcon(netuse); + (void) smbrdr_tdcon(netuse); smbrdr_netuse_put(netuse); rc = 0; } @@ -264,17 +264,17 @@ smbrdr_tree_disconnect(unsigned short tid) } /* - * smbrdr_smb_tdcon + * smbrdr_tdcon * * Disconnect a share. This message informs the server that we no longer * wish to access the resource specified by tid, obtained via a prior - * mlsvc_tree_connect. The tid is passed in the SMB header so the setup + * smbrdr_tree_connect. The tid is passed in the SMB header so the setup * for this call is very straightforward. * * Returns 0 on success. Otherwise returns a -ve error code. */ static int -smbrdr_smb_tdcon(struct sdb_netuse *netuse) +smbrdr_tdcon(struct sdb_netuse *netuse) { struct sdb_session *session; smbrdr_handle_t srh; @@ -285,7 +285,7 @@ smbrdr_smb_tdcon(struct sdb_netuse *netuse) netuse->state = SDB_NSTATE_DISCONNECTING; smbrdr_ofile_end_of_share(netuse->tid); - if ((session = netuse->session) == 0) { + if ((session = netuse->session) == NULL) { smbrdr_netuse_clear(netuse); return (0); } @@ -300,7 +300,7 @@ smbrdr_smb_tdcon(struct sdb_netuse *netuse) session, &session->logon, netuse); if (status != NT_STATUS_SUCCESS) { - syslog(LOG_ERR, "smbrdr: (tdcon) %s", xlate_nt_status(status)); + syslog(LOG_DEBUG, "smbrdr_tdcon: %s", xlate_nt_status(status)); /* should we clear here? */ smbrdr_netuse_clear(netuse); return (-1); @@ -308,7 +308,7 @@ smbrdr_smb_tdcon(struct sdb_netuse *netuse) rc = smb_msgbuf_encode(&srh.srh_mbuf, "bw.", 0, 0); if (rc < 0) { - syslog(LOG_ERR, "smbrdr: (tdcon) encode failed"); + syslog(LOG_DEBUG, "smbrdr_tdcon: encode failed"); smbrdr_handle_free(&srh); /* should we clear here? */ smbrdr_netuse_clear(netuse); @@ -317,7 +317,7 @@ smbrdr_smb_tdcon(struct sdb_netuse *netuse) status = smbrdr_exchange(&srh, &smb_hdr, 0); if (status != NT_STATUS_SUCCESS) { - syslog(LOG_ERR, "smbrdr: (tdcon) %s", xlate_nt_status(status)); + syslog(LOG_DEBUG, "smbrdr_tdcon: %s", xlate_nt_status(status)); rc = -1; } else { rc = 0; @@ -347,10 +347,8 @@ smbrdr_netuse_alloc(struct sdb_session *session, char *sharename) struct sdb_netuse *netuse; int i; - if (session == 0 || sharename == 0) { - syslog(LOG_ERR, "smbrdr: (tcon) invalid arg"); - return (0); - } + if (session == NULL || sharename == NULL) + return (NULL); for (i = 0; i < N_NETUSE_TABLE; ++i) { netuse = &netuse_table[i]; @@ -369,7 +367,7 @@ smbrdr_netuse_alloc(struct sdb_session *session, char *sharename) (void) mutex_unlock(&netuse->mtx); } - syslog(LOG_WARNING, "smbrdr: (tcon) table full"); + syslog(LOG_DEBUG, "smbrdr_netuse_alloc: table full"); return (0); } @@ -431,7 +429,7 @@ smbrdr_netuse_get(int tid) (void) mutex_unlock(&netuse->mtx); } - syslog(LOG_WARNING, "smbrdr: (lookup) no such TID %d", tid); + syslog(LOG_DEBUG, "smbrdr_netuse_get: %d: no such TID", tid); return (0); } diff --git a/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_read_andx.c b/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_read_andx.c index ef90fa79ac..3b2fc4dd7a 100644 --- a/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_read_andx.c +++ b/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_read_andx.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -33,7 +33,6 @@ #include <strings.h> #include <smbsrv/libsmbrdr.h> - #include <smbsrv/netbios.h> #include <smbsrv/ntstatus.h> #include <smbrdr.h> @@ -46,15 +45,13 @@ static int smbrdr_decode_readx_rsp(smb_msgbuf_t *, char *, unsigned, smb_read_andx_rsp_t *); -static void smbrdr_dump_readx_rsp(smb_read_andx_rsp_t *); - /* - * smbrdr_rpc_readx + * smbrdr_readx * * Send SMB_COM_READ_ANDX request. */ int -smbrdr_rpc_readx(int fid, char *in_buf, int in_len) +smbrdr_readx(int fid, char *in_buf, int in_len) { struct sdb_netuse *netuse; struct sdb_ofile *ofile; @@ -64,7 +61,7 @@ smbrdr_rpc_readx(int fid, char *in_buf, int in_len) DWORD status; int rc, max_return; - if ((ofile = smbrdr_ofile_get(fid)) == 0) + if ((ofile = smbrdr_ofile_get(fid)) == NULL) return (-1); netuse = ofile->netuse; @@ -73,7 +70,7 @@ smbrdr_rpc_readx(int fid, char *in_buf, int in_len) netuse->session, &netuse->session->logon, netuse); if (status != NT_STATUS_SUCCESS) { - syslog(LOG_ERR, "SmbrdrReadAndx: %s", xlate_nt_status(status)); + syslog(LOG_DEBUG, "smbrdr_readx: %s", xlate_nt_status(status)); smbrdr_ofile_put(ofile); return (-1); } @@ -104,7 +101,7 @@ smbrdr_rpc_readx(int fid, char *in_buf, int in_len) 0); /* Count of data bytes = 0 */ if (rc < 0) { - syslog(LOG_ERR, "SmbrdrReadAndx: smbrdr_prep_readx_req failed"); + syslog(LOG_DEBUG, "smbrdr_readx: prep failed"); smbrdr_handle_free(&srh); smbrdr_ofile_put(ofile); return (rc); @@ -117,14 +114,14 @@ smbrdr_rpc_readx(int fid, char *in_buf, int in_len) smbrdr_unlock_transport(); smbrdr_handle_free(&srh); smbrdr_ofile_put(ofile); - syslog(LOG_ERR, "SmbrdrReadAndx: send failed"); + syslog(LOG_DEBUG, "smbrdr_readx: send failed"); return (-1); } status = smbrdr_rcv(&srh, 1); if (status != NT_STATUS_SUCCESS) { - syslog(LOG_ERR, "SmbrdrReadAndx: nb_rcv failed"); + syslog(LOG_DEBUG, "smbrdr_readx: nb_rcv failed"); smbrdr_unlock_transport(); smbrdr_handle_free(&srh); smbrdr_ofile_put(ofile); @@ -134,7 +131,7 @@ smbrdr_rpc_readx(int fid, char *in_buf, int in_len) rc = smbrdr_decode_readx_rsp(mb, in_buf, in_len, &rsp); if (rc < 0) { - syslog(LOG_ERR, "SmbrdrReadAndx: read decode failure!"); + syslog(LOG_DEBUG, "smbrdr_readx: decode failed"); smbrdr_unlock_transport(); smbrdr_handle_free(&srh); smbrdr_ofile_put(ofile); @@ -148,20 +145,6 @@ smbrdr_rpc_readx(int fid, char *in_buf, int in_len) return ((rc < 0) ? rc : rsp.DataLength); } -static void -smbrdr_dump_readx_rsp(smb_read_andx_rsp_t *rsp) -{ - - syslog(LOG_DEBUG, "[SmbReadX Rsp] WordCount:%x,AndXCmd:%x," - " AndXReserved:%x, AndXOffset:%d", - rsp->WordCount, rsp->AndXCmd, rsp->AndXReserved, rsp->AndXOffset); - - syslog(LOG_DEBUG, "[SmbReadX Rsp] Remaining:%d, Mode:%d, Reserved:%x, " - "DataLen:%d, DataOffset:%d, ByteCount: %d", - rsp->Remaining, rsp->DataCompactionMode, rsp->Reserved, - rsp->DataLength, rsp->DataOffset, rsp->ByteCount); -} - /* * smbrdr_decode_readx_rsp * @@ -198,9 +181,6 @@ smbrdr_decode_readx_rsp(smb_msgbuf_t *mb, if (rc <= 0) return (-1); - smbrdr_dump_readx_rsp(rsp); - - /* it should never happen, but check anyway */ if (rsp->DataLength > in_len) return (-1); diff --git a/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_rpcpipe.c b/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_rpcpipe.c index b89eddf275..3059a0cf0e 100644 --- a/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_rpcpipe.c +++ b/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_rpcpipe.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -38,14 +38,12 @@ #include <synch.h> #include <smbsrv/libsmbrdr.h> - #include <smbsrv/ntstatus.h> #include <smbrdr.h> -static int smbrdr_smb_close(struct sdb_ofile *ofile); -static DWORD smbrdr_smb_ntcreate(struct sdb_ofile *ofile); -static struct sdb_ofile *smbrdr_ofile_alloc(struct sdb_netuse *netuse, - char *name); +static int smbrdr_close(struct sdb_ofile *); +static DWORD smbrdr_ntcreatex(struct sdb_ofile *); +static struct sdb_ofile *smbrdr_ofile_alloc(struct sdb_netuse *, char *); static void smbrdr_ofile_clear(struct sdb_ofile *ofile) @@ -86,24 +84,24 @@ mlsvc_open_pipe(char *hostname, char *domain, char *username, char *pipename) int retry; struct timespec st; - tid = mlsvc_tree_connect(hostname, username, "IPC$"); + tid = smbrdr_tree_connect(hostname, username, "IPC$"); if (tid == 0) { - syslog(LOG_ERR, "smbrdr: (open) %s %s %s %s %s", + syslog(LOG_DEBUG, "smbrdr: (open) %s %s %s %s %s", hostname, domain, username, pipename, xlate_nt_status(NT_STATUS_UNEXPECTED_NETWORK_ERROR)); return (-1); } netuse = smbrdr_netuse_get(tid); - if (netuse == 0) { - syslog(LOG_ERR, "smbrdr: (open) %s %s %s %s %s", + if (netuse == NULL) { + syslog(LOG_DEBUG, "smbrdr: (open) %s %s %s %s %s", hostname, domain, username, pipename, xlate_nt_status(NT_STATUS_CONNECTION_INVALID)); return (-1); } if ((ofile = smbrdr_ofile_alloc(netuse, pipename)) == 0) { - syslog(LOG_ERR, "smbrdr: (open) %s %s %s %s %s", + syslog(LOG_DEBUG, "smbrdr: (open) %s %s %s %s %s", hostname, domain, username, pipename, xlate_nt_status(NT_STATUS_INSUFFICIENT_RESOURCES)); smbrdr_netuse_put(netuse); @@ -113,7 +111,7 @@ mlsvc_open_pipe(char *hostname, char *domain, char *username, char *pipename) status = NT_STATUS_OPEN_FAILED; for (retry = 0; retry < mlsvc_pipe_recon_tries; retry++) { - status = smbrdr_smb_ntcreate(ofile); + status = smbrdr_ntcreatex(ofile); switch (status) { case NT_STATUS_SUCCESS: @@ -163,13 +161,11 @@ mlsvc_close_pipe(int fid) unsigned short tid; int rc; - if ((ofile = smbrdr_ofile_get(fid)) == 0) { - syslog(LOG_ERR, "mlsvc_close_pipe: unknown file (%d)", fid); + if ((ofile = smbrdr_ofile_get(fid)) == NULL) return (-1); - } tid = ofile->tid; - rc = smbrdr_smb_close(ofile); + rc = smbrdr_close(ofile); smbrdr_ofile_put(ofile); if (rc == 0) @@ -238,8 +234,7 @@ smbrdr_ofile_get(int fid) (void) mutex_unlock(&ofile->mtx); } - syslog(LOG_WARNING, "smbrdr: (lookup) no such FID %d", fid); - return (0); + return (NULL); } /* @@ -261,7 +256,7 @@ smbrdr_ofile_end_of_share(unsigned short tid) ofile = &ofile_table[i]; (void) mutex_lock(&ofile->mtx); if (ofile->tid == tid) - (void) smbrdr_smb_close(ofile); + (void) smbrdr_close(ofile); (void) mutex_unlock(&ofile->mtx); } } @@ -300,12 +295,12 @@ smbrdr_dump_ofiles() */ /* - * smbrdr_smb_close + * smbrdr_close * * Send SMBClose request for the given open file. */ static int -smbrdr_smb_close(struct sdb_ofile *ofile) +smbrdr_close(struct sdb_ofile *ofile) { struct sdb_session *session; struct sdb_netuse *netuse; @@ -316,12 +311,12 @@ smbrdr_smb_close(struct sdb_ofile *ofile) int fid; int rc; - if (ofile == 0) + if (ofile == NULL) return (0); ofile->state = SDB_FSTATE_CLOSING; - if ((session = ofile->session) == 0) { + if ((session = ofile->session) == NULL) { smbrdr_ofile_clear(ofile); return (0); } @@ -341,20 +336,12 @@ smbrdr_smb_close(struct sdb_ofile *ofile) session, logon, netuse); if (status != NT_STATUS_SUCCESS) { - syslog(LOG_ERR, "SmbrdrClose: %s", xlate_nt_status(status)); smbrdr_ofile_clear(ofile); return (-1); } - rc = smb_msgbuf_encode(&srh.srh_mbuf, - "(wct)b (fid)w (lwrtm)l (bcc)w (pad).", - 3, /* WordCount */ - fid, /* Fid */ - 0x00000000ul, /* LastWriteTime */ - 0); /* ByteCount */ - + rc = smb_msgbuf_encode(&srh.srh_mbuf, "bwlw.", 3, fid, 0x00000000ul, 0); if (rc <= 0) { - syslog(LOG_ERR, "SmbrdrClose: encode failed"); smbrdr_handle_free(&srh); smbrdr_ofile_clear(ofile); return (-1); @@ -362,7 +349,7 @@ smbrdr_smb_close(struct sdb_ofile *ofile) status = smbrdr_exchange(&srh, &smb_hdr, 0); if (status != NT_STATUS_SUCCESS) - syslog(LOG_ERR, "SmbrdrClose: %s", xlate_nt_status(status)); + syslog(LOG_DEBUG, "smbrdr_close: %s", xlate_nt_status(status)); smbrdr_handle_free(&srh); smbrdr_ofile_clear(ofile); @@ -405,19 +392,18 @@ smbrdr_ofile_alloc(struct sdb_netuse *netuse, char *name) (void) mutex_unlock(&ofile->mtx); } - syslog(LOG_WARNING, "smbrdr: (open) table full"); - return (0); + return (NULL); } /* - * smbrdr_smb_ntcreate + * smbrdr_ntcreatex * * This will do an SMB_COM_NT_CREATE_ANDX with lots of default values. * All of the underlying session and share data should already be set * up before we get here. If everything works we'll get a valid fid. */ static DWORD -smbrdr_smb_ntcreate(struct sdb_ofile *ofile) +smbrdr_ntcreatex(struct sdb_ofile *ofile) { struct sdb_logon *logon; struct sdb_netuse *netuse; @@ -458,13 +444,14 @@ smbrdr_smb_ntcreate(struct sdb_ofile *ofile) null_size = sizeof (char); } - syslog(LOG_DEBUG, "SmbRdrNtCreate: %d %s", path_len, path); + syslog(LOG_DEBUG, "smbrdr_ntcreatex: %d %s", path_len, path); status = smbrdr_request_init(&srh, SMB_COM_NT_CREATE_ANDX, sess, logon, netuse); if (status != NT_STATUS_SUCCESS) { - syslog(LOG_ERR, "SmbrdrNtCreate: %s", xlate_nt_status(status)); + syslog(LOG_DEBUG, "smbrdr_ntcreatex: %s", + xlate_nt_status(status)); return (NT_STATUS_INVALID_PARAMETER_1); } diff --git a/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_session.c b/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_session.c index 535ad537d9..6bcba07778 100644 --- a/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_session.c +++ b/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_session.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -61,38 +61,17 @@ static uint16_t smbrdr_ports[] = { static int smbrdr_nports = sizeof (smbrdr_ports) / sizeof (smbrdr_ports[0]); -/* - * Pointer to the PDC location interface. - * To be set up by SMB when it loads. - */ -static mlsvc_locate_pdc_t mlsvc_locate_pdc; - -/* - * This is a temporary hack to stop the DC from closing a session - * due to inactivity. - */ -#define MLSVC_SESSION_FORCE_KEEPALIVE 10 - -/* - * This is the session data table. - * - * The rwlock synchronizes access to the session table - * - * The mutex is to make session lookup and create atomic - * so we don't end up with two sessions with the same - * system. - */ static struct sdb_session session_table[MLSVC_DOMAIN_MAX]; static mutex_t smbrdr_screate_mtx; -static unsigned int session_id = 0; +static uint32_t session_id = 0; -static struct sdb_session *smbrdr_session_init(smb_ntdomain_t *di); +static struct sdb_session *smbrdr_session_init(smb_ntdomain_t *); static int smbrdr_trnsprt_connect(struct sdb_session *, uint16_t); -static int smbrdr_session_connect(smb_ntdomain_t *di); -static int smbrdr_smb_negotiate(struct sdb_session *session); -static int smbrdr_smb_echo(struct sdb_session *session); -static void smbrdr_session_disconnect(struct sdb_session *session, int cleanup); -static int smbrdr_locate_dc(char *domain); +static int smbrdr_session_connect(smb_ntdomain_t *); +static int smbrdr_smb_negotiate(struct sdb_session *); +static int smbrdr_echo(struct sdb_session *); +static void smbrdr_session_disconnect(struct sdb_session *, int); + static void smbrdr_session_clear(struct sdb_session *session) @@ -101,33 +80,6 @@ smbrdr_session_clear(struct sdb_session *session) } /* - * mlsvc_install_pdc_cb - * - * Function to be called by SMB initialization code to set up a - * callback to the PDC location interface. - */ -void -mlsvc_install_pdc_cb(mlsvc_locate_pdc_t locate_pdc_cb) -{ - mlsvc_locate_pdc = locate_pdc_cb; -} - -/* - * mlsvc_locate_domain_controller - * - * Locate a domain controller. Note that this may close an existing - * connection to the current domain controller. - */ -int -mlsvc_locate_domain_controller(char *domain) -{ - if (mlsvc_locate_pdc) - return (mlsvc_locate_pdc(domain)); - - return (0); -} - -/* * Entry pointy for smbrdr initialization. */ void @@ -168,25 +120,17 @@ mlsvc_disconnect(char *server) * * Returns 0 on success, otherwise -1. */ +/*ARGSUSED*/ int -smbrdr_negotiate(char *domain_name) +smbrdr_negotiate(char *domain) { struct sdb_session *session = 0; smb_ntdomain_t *di; int retry = 1; int res = 0; - if ((di = smb_getdomaininfo(0)) == 0) { - /* - * Attempting to locate a domain controller - * will shutdown an existing PDC connection. - */ - (void) smbrdr_locate_dc(domain_name); - di = smb_getdomaininfo(0); - } - - if (di == 0) { - syslog(LOG_ERR, "smbrdr: negotiate (cannot access domain)"); + if ((di = smb_getdomaininfo(0)) == NULL) { + syslog(LOG_DEBUG, "smbrdr_negotiate: cannot access domain"); return (-1); } @@ -198,7 +142,7 @@ smbrdr_negotiate(char *domain_name) (void) mutex_lock(&smbrdr_screate_mtx); while (retry > 0) { session = smbrdr_session_lock(di->server, 0, SDB_SLCK_WRITE); - if (session != 0) { + if (session != 0) { if (nb_keep_alive(session->sock) == 0) { /* session is good, use it */ smbrdr_session_unlock(session); @@ -212,12 +156,8 @@ smbrdr_negotiate(char *domain_name) if (smbrdr_session_connect(di) != 0) { if (retry > 0) { - /* Do we really need to do this here? */ - (void) smbrdr_locate_dc(domain_name); di = smb_getdomaininfo(0); - if (di == 0) { - syslog(LOG_ERR, "smbrdr: negotiate" - " (cannot access domain)"); + if (di == NULL) { res = -1; break; } @@ -230,6 +170,8 @@ smbrdr_negotiate(char *domain_name) } (void) mutex_unlock(&smbrdr_screate_mtx); + if (di == NULL) + syslog(LOG_DEBUG, "smbrdr_negotiate: cannot access domain"); return (res); } @@ -254,8 +196,8 @@ smbrdr_session_connect(smb_ntdomain_t *di) * be accessible until it's established otherwise another thread * might get access to a session which is not fully established. */ - if ((session = smbrdr_session_init(di)) == 0) { - syslog(LOG_ERR, "smbrdr: session init failed"); + if ((session = smbrdr_session_init(di)) == NULL) { + syslog(LOG_DEBUG, "smbrdr_session_init failed"); return (-1); } @@ -275,7 +217,7 @@ smbrdr_session_connect(smb_ntdomain_t *di) if (rc < 0) { smbrdr_session_clear(session); smbrdr_session_unlock(session); - syslog(LOG_ERR, "smbrdr: NBT/TCP connect failed"); + syslog(LOG_DEBUG, "smbrdr: connect failed"); return (-1); } @@ -283,7 +225,7 @@ smbrdr_session_connect(smb_ntdomain_t *di) (void) close(session->sock); smbrdr_session_clear(session); smbrdr_session_unlock(session); - syslog(LOG_ERR, "smbrdr: SMB negotiate failed"); + syslog(LOG_DEBUG, "smbrdr: negotiate failed"); return (-1); } @@ -313,11 +255,7 @@ smbrdr_trnsprt_connect(struct sdb_session *sess, uint16_t port) unsigned int cpid = oem_get_smb_cpid(); if ((sock = socket(AF_INET, SOCK_STREAM, 0)) <= 0) { - /* - * We should never see descriptor 0 (stdin). - */ - syslog(LOG_ERR, "smbrdr: socket(%d) failed (%s)", sock, - strerror(errno)); + syslog(LOG_DEBUG, "smbrdr: socket failed: %s", strerror(errno)); return (-1); } @@ -327,7 +265,8 @@ smbrdr_trnsprt_connect(struct sdb_session *sess, uint16_t port) sin.sin_port = htons(port); if ((rc = connect(sock, (struct sockaddr *)&sin, sizeof (sin))) < 0) { - syslog(LOG_ERR, "smbrdr: connect failed (%s)", strerror(errno)); + syslog(LOG_DEBUG, "smbrdr: connect failed: %s", + strerror(errno)); if (sock != 0) (void) close(sock); return (-1); @@ -338,7 +277,7 @@ smbrdr_trnsprt_connect(struct sdb_session *sess, uint16_t port) rc = unicodestooems(server_name, unicode_server_name, SMB_PI_MAX_DOMAIN, cpid); if (rc == 0) { - syslog(LOG_ERR, "smbrdr: unicode conversion failed"); + syslog(LOG_DEBUG, "smbrdr: unicode conversion failed"); if (sock != 0) (void) close(sock); return (-1); @@ -352,7 +291,7 @@ smbrdr_trnsprt_connect(struct sdb_session *sess, uint16_t port) */ if (port == SSN_SRVC_TCP_PORT) { if (smb_getnetbiosname(hostname, MAXHOSTNAMELEN) != 0) { - syslog(LOG_ERR, "smbrdr: no hostname"); + syslog(LOG_DEBUG, "smbrdr: no hostname"); if (sock != 0) (void) close(sock); return (-1); @@ -362,7 +301,7 @@ smbrdr_trnsprt_connect(struct sdb_session *sess, uint16_t port) server_name, sess->scope, hostname, sess->scope); if (rc != 0) { - syslog(LOG_ERR, + syslog(LOG_DEBUG, "smbrdr: NBT session request to %s failed %d", server_name, rc); if (sock != 0) @@ -404,28 +343,19 @@ smbrdr_smb_negotiate(struct sdb_session *sess) status = smbrdr_request_init(&srh, SMB_COM_NEGOTIATE, sess, 0, 0); - if (status != NT_STATUS_SUCCESS) { - syslog(LOG_ERR, "smbrdr: negotiate (%s)", - xlate_nt_status(status)); + if (status != NT_STATUS_SUCCESS) return (-1); - } mb = &srh.srh_mbuf; - rc = smb_msgbuf_encode(mb, "(wct)b (bcc)w (dialect)bs", - 0, /* smb_wct */ - 12, /* smb_bcc */ - 0x02, /* dialect marker */ - "NT LM 0.12"); /* only dialect we care about */ - + rc = smb_msgbuf_encode(mb, "bwbs", 0, 12, 0x02, "NT LM 0.12"); if (rc <= 0) { - syslog(LOG_ERR, "smbrdr: negotiate (encode failed)"); smbrdr_handle_free(&srh); return (-1); } status = smbrdr_exchange(&srh, &smb_hdr, 0); if (status != NT_STATUS_SUCCESS) { - syslog(LOG_ERR, "smbrdr: negotiate (%s)", + syslog(LOG_DEBUG, "smbrdr: negotiate: %s", xlate_nt_status(status)); smbrdr_handle_free(&srh); return (-1); @@ -436,12 +366,11 @@ smbrdr_smb_negotiate(struct sdb_session *sess) sess->challenge_len = 0; rc = smb_msgbuf_decode(mb, - "(wordcnt)1.(dialect)w(secm)b12.(skey)l(cap)l10.(klen)b2.", + "1.(dialect)w(mode)b12.(key)l(cap)l10.(keylen)b2.", &dialect, &tmp_secmode, &sess->sesskey, &sess->remote_caps, &tmp_clen); if (rc <= 0 || dialect != 0) { - syslog(LOG_ERR, "smbrdr: negotiate (response error)"); smbrdr_handle_free(&srh); return (-1); } @@ -451,7 +380,6 @@ smbrdr_smb_negotiate(struct sdb_session *sess) rc = smb_msgbuf_decode(mb, "#c", sess->challenge_len, sess->challenge_key); if (rc <= 0) { - syslog(LOG_ERR, "smbrdr: negotiate (decode error)"); smbrdr_handle_free(&srh); return (-1); } @@ -461,7 +389,7 @@ smbrdr_smb_negotiate(struct sdb_session *sess) if ((sess->secmode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED) && (sess->secmode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED)) { sess->sign_ctx.ssc_flags |= SMB_SCF_REQUIRED; - syslog(LOG_DEBUG, "smbrdr: %s requires signing", + syslog(LOG_DEBUG, "smbrdr: %s: signing required", sess->di.server); } @@ -482,12 +410,11 @@ smbrdr_smb_negotiate(struct sdb_session *sess) static struct sdb_session * smbrdr_session_init(smb_ntdomain_t *di) { - struct sdb_session *session = 0; + struct sdb_session *session = NULL; int i; - char *p; - if (di == 0) - return (0); + if (di == NULL) + return (NULL); for (i = 0; i < MLSVC_DOMAIN_MAX; ++i) { session = &session_table[i]; @@ -499,10 +426,8 @@ smbrdr_session_init(smb_ntdomain_t *di) (void) utf8_strupr(session->di.domain); (void) utf8_strupr(session->di.server); - smb_config_rdlock(); - p = smb_config_getstr(SMB_CI_NBSCOPE); - (void) strlcpy(session->scope, p, SMB_PI_MAX_SCOPE); - smb_config_unlock(); + (void) smb_config_getstr(SMB_CI_NBSCOPE, session->scope, + sizeof (session->scope)); (void) strlcpy(session->native_os, "Solaris", SMB_PI_MAX_NATIVE_OS); @@ -530,8 +455,8 @@ smbrdr_session_init(smb_ntdomain_t *di) (void) rw_unlock(&session->rwl); } - syslog(LOG_WARNING, "smbrdr: no session available"); - return (0); + syslog(LOG_DEBUG, "smbrdr: no session available"); + return (NULL); } /* @@ -550,10 +475,8 @@ smbrdr_session_disconnect(struct sdb_session *session, int cleanup) { int state; - if (session == 0) { - syslog(LOG_ERR, "smbrdr: (disconnect) null session"); + if (session == NULL) return; - } state = session->state; if ((state != SDB_SSTATE_DISCONNECTING) && @@ -567,7 +490,7 @@ smbrdr_session_disconnect(struct sdb_session *session, int cleanup) */ session->state = (state == SDB_SSTATE_STALE) ? SDB_SSTATE_CLEANING : SDB_SSTATE_DISCONNECTING; - (void) smbrdr_smb_logoff(&session->logon); + (void) smbrdr_logoffx(&session->logon); nb_close(session->sock); smbrdr_session_clear(session); } @@ -605,10 +528,8 @@ smbrdr_session_lock(char *server, char *username, int lmode) struct sdb_session *session; int i; - if (server == 0) { - syslog(LOG_ERR, "smbrdr: (lookup) no server specified"); - return (0); - } + if (server == NULL) + return (NULL); for (i = 0; i < MLSVC_DOMAIN_MAX; ++i) { session = &session_table[i]; @@ -624,7 +545,7 @@ smbrdr_session_lock(char *server, char *username, int lmode) return (session); (void) rw_unlock(&session->rwl); - return (0); + return (NULL); } return (session); } @@ -632,7 +553,7 @@ smbrdr_session_lock(char *server, char *username, int lmode) (void) rw_unlock(&session->rwl); } - return (0); + return (NULL); } /* @@ -649,13 +570,11 @@ mlsvc_session_native_values(int fid, int *remote_os, struct sdb_netuse *netuse; struct sdb_ofile *ofile; - if (remote_os == 0 || remote_lm == 0) { - syslog(LOG_ERR, "mlsvc_session_native_values: null"); + if (remote_os == NULL || remote_lm == NULL) return (-1); - } if ((ofile = smbrdr_ofile_get(fid)) == 0) { - syslog(LOG_ERR, + syslog(LOG_DEBUG, "mlsvc_session_native_values: unknown file (%d)", fid); return (-1); } @@ -672,96 +591,6 @@ mlsvc_session_native_values(int fid, int *remote_os, } /* - * smbrdr_disconnect_sessions - * - * Disconnects/cleanups all the sessions - */ -static void -smbrdr_disconnect_sessions(int cleanup) -{ - struct sdb_session *session; - int i; - - for (i = 0; i < MLSVC_DOMAIN_MAX; ++i) { - session = &session_table[i]; - (void) rw_wrlock(&session->rwl); - smbrdr_session_disconnect(&session_table[i], cleanup); - (void) rw_unlock(&session->rwl); - } -} - - -/* - * mlsvc_check_sessions - * - * This function should be run in an independent thread. At the time of - * writing it is called periodically from an infinite loop in the start - * up thread once initialization is complete. It sends a NetBIOS keep- - * alive message on each active session and handles cleanup if a session - * is closed from the remote end. Testing demonstrated that the domain - * controller will close a session after 15 minutes of inactivity. Note - * that neither NetBIOS keep-alive nor SMB echo is deemed as activity - * in this case, however, RPC requests appear to reset the timeout and - * keep the session open. Note that the NetBIOS request does stop the - * remote NetBIOS layer from timing out the connection. - */ -void -mlsvc_check_sessions(void) -{ - static int session_keep_alive; - struct sdb_session *session; - smb_ntdomain_t di; - int i; - - ++session_keep_alive; - - for (i = 0; i < MLSVC_DOMAIN_MAX; ++i) { - session = &session_table[i]; - - (void) rw_wrlock(&session->rwl); - - if (session->state < SDB_SSTATE_CONNECTED) { - (void) rw_unlock(&session->rwl); - continue; - } - - /* - * NetBIOS is only used on with port 139. The keep alive - * is not relevant over NetBIOS-less SMB over port 445. - * This is just to see if the socket is still alive. - */ - if (session->port == SSN_SRVC_TCP_PORT) { - if (nb_keep_alive(session->sock) != 0) { - session->state = SDB_SSTATE_STALE; - (void) rw_unlock(&session->rwl); - continue; - } - } - - if (session_keep_alive >= MLSVC_SESSION_FORCE_KEEPALIVE) { - if (smbrdr_smb_echo(session) != 0) { - syslog(LOG_WARNING, - "smbrdr: monitor[%s] cannot contact %s", - session->di.domain, session->di.server); - (void) memcpy(&di, &session->di, - sizeof (smb_ntdomain_t)); - session->state = SDB_SSTATE_STALE; - (void) rw_unlock(&session->rwl); - if (smb_getdomaininfo(0) == 0) - (void) smbrdr_locate_dc(di.domain); - } - } else - (void) rw_unlock(&session->rwl); - } - - if (session_keep_alive >= MLSVC_SESSION_FORCE_KEEPALIVE) { - session_keep_alive = 0; - /* cleanup */ - smbrdr_disconnect_sessions(1); - } -} - -/* * smbrdr_dump_sessions * * Debug function to dump the session table. @@ -812,7 +641,7 @@ mlsvc_echo(char *server) if ((session = smbrdr_session_lock(server, 0, SDB_SLCK_WRITE)) == 0) return (1); - if (smbrdr_smb_echo(session) != 0) { + if (smbrdr_echo(session) != 0) { session->state = SDB_SSTATE_STALE; res = -1; } @@ -822,7 +651,7 @@ mlsvc_echo(char *server) } /* - * smbrdr_smb_echo + * smbrdr_echo * * This request can be used to test the connection to the server. The * server should echo the data sent. The server should ignore the tid @@ -832,7 +661,7 @@ mlsvc_echo(char *server) * Return 0 on success. Otherwise return a -ve error code. */ static int -smbrdr_smb_echo(struct sdb_session *session) +smbrdr_echo(struct sdb_session *session) { static char *echo_str = "smbrdr"; smbrdr_handle_t srh; @@ -847,43 +676,21 @@ smbrdr_smb_echo(struct sdb_session *session) } status = smbrdr_request_init(&srh, SMB_COM_ECHO, session, 0, 0); - - if (status != NT_STATUS_SUCCESS) { - syslog(LOG_ERR, "SmbrdrEcho: %s", xlate_nt_status(status)); + if (status != NT_STATUS_SUCCESS) return (-1); - } rc = smb_msgbuf_encode(&srh.srh_mbuf, "bwws", 1, 1, strlen(echo_str), echo_str); if (rc <= 0) { - syslog(LOG_ERR, "SmbrdrEcho: encode failed"); smbrdr_handle_free(&srh); return (-1); } status = smbrdr_exchange(&srh, &smb_hdr, 10); - if (status != NT_STATUS_SUCCESS) { - syslog(LOG_ERR, "SmbrdrEcho: %s", xlate_nt_status(status)); - rc = -1; - } else { - rc = 0; - } - smbrdr_handle_free(&srh); - return (rc); -} -/* - * smbrdr_locate_dc - * - * Locate a domain controller. Note that this may close an existing - * connection to the current domain controller. - */ -static int -smbrdr_locate_dc(char *domain) -{ - if (mlsvc_locate_pdc) - return (mlsvc_locate_pdc(domain)); + if (status != NT_STATUS_SUCCESS) + return (-1); return (0); } diff --git a/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_transact.c b/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_transact.c index 24bf3a5cea..1fea4e831d 100644 --- a/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_transact.c +++ b/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_transact.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -33,7 +33,6 @@ #include <strings.h> #include <smbsrv/libsmbrdr.h> - #include <smbsrv/ntstatus.h> #include <smbsrv/smb.h> #include <smbrdr.h> @@ -54,13 +53,12 @@ static int decode_smb_transact(smb_msgbuf_t *, char *, unsigned, smb_transact_rsp_t *); /* - * smbrdr_rpc_transact + * smbrdr_transact * * Send a SMB_COM_TRANSACTION request. */ int -smbrdr_rpc_transact(int fid, char *out_buf, int out_len, - char *in_buf, int in_len) +smbrdr_transact(int fid, char *out_buf, int out_len, char *in_buf, int in_len) { struct sdb_session *session; struct sdb_netuse *netuse; @@ -86,7 +84,8 @@ smbrdr_rpc_transact(int fid, char *out_buf, int out_len, session, logon, netuse); if (status != NT_STATUS_SUCCESS) { - syslog(LOG_ERR, "SmbrdrTransact: %s", xlate_nt_status(status)); + syslog(LOG_DEBUG, "smbrdr_transact: %s", + xlate_nt_status(status)); smbrdr_ofile_put(ofile); return (-1); } @@ -96,8 +95,7 @@ smbrdr_rpc_transact(int fid, char *out_buf, int out_len, rc = prep_smb_transact(mb, ofile->fid, out_buf, out_len, in_len, session->remote_caps & CAP_UNICODE); if (rc < 0) { - syslog(LOG_ERR, - "smbrdr_rpc_transact: prep_smb_transact failed"); + syslog(LOG_DEBUG, "smbrdr_transact: prep failed"); smbrdr_handle_free(&srh); smbrdr_ofile_put(ofile); return (rc); @@ -110,7 +108,7 @@ smbrdr_rpc_transact(int fid, char *out_buf, int out_len, smbrdr_unlock_transport(); smbrdr_handle_free(&srh); smbrdr_ofile_put(ofile); - syslog(LOG_ERR, "smbrdr_rpc_transact: send failed"); + syslog(LOG_DEBUG, "smbrdr_transact: send failed"); return (-1); } @@ -120,15 +118,15 @@ smbrdr_rpc_transact(int fid, char *out_buf, int out_len, do { if (smbrdr_rcv(&srh, first_rsp) != NT_STATUS_SUCCESS) { - syslog(LOG_ERR, "smbrdr_rpc_transact: nb_rcv failed"); + syslog(LOG_DEBUG, "smbrdr_transact: nb_rcv failed"); rc = -1; break; } rc = decode_smb_transact(mb, in_buf, cur_inlen, &rsp); if (rc < 0 || rsp.TotalDataCount > in_len) { - syslog(LOG_ERR, - "SmbTransact: transact decode failure!"); + syslog(LOG_DEBUG, + "smbrdr_transact: decode failed"); rc = -1; break; } @@ -222,7 +220,6 @@ decode_smb_transact(smb_msgbuf_t *mb, char *in, unsigned in_len, rc = smb_msgbuf_decode(mb, "b", &rsp->WordCount); if (rc <= 0 || rsp->WordCount < 10) { - syslog(LOG_ERR, "SmbTransact: invalid word count"); return (-1); } |
