From 1fdeec650620e8498c06f832ea4bd2292f7e9632 Mon Sep 17 00:00:00 2001 From: joyce mcintosh Date: Mon, 26 Jul 2010 15:02:13 -0700 Subject: [PATCH] 6779186 need domain controller hot failover 6970986 Level II oplocks - smb_oplock_grant_t shouldn't be dynamically allocated 6971031 Unable add ACL on the share which has only the default owner tab by ZFS 6971899 OpenSSL not MT-safe and takes down smbd 6936762 libidmap should transparently handle interruption in connection to idmapd 6954902 mapping to unknown type does not use directory-based mapping information --HG-- rename : usr/src/lib/libidmap/common/idmap_priv.h => usr/src/cmd/idmap/idmap/namemaps.h --- usr/src/cmd/idmap/idmap/idmap.c | 131 +++--------- usr/src/cmd/idmap/idmap/namemaps.c | 18 +- usr/src/cmd/idmap/idmap/namemaps.h | 2 +- usr/src/cmd/idmap/idmapd/idmapd.h | 27 +-- usr/src/cmd/smbsrv/smbd/server.xml | 2 +- usr/src/cmd/smbsrv/smbd/smbd.h | 8 +- usr/src/cmd/smbsrv/smbd/smbd_join.c | 186 ++++++++++------ usr/src/cmd/smbsrv/smbd/smbd_main.c | 89 ++++---- usr/src/common/smbclnt/smbfs_ntacl.c | 27 +-- usr/src/lib/libidmap/common/idmap.h | 12 +- usr/src/lib/libidmap/common/idmap_api.c | 247 ++++------------------ usr/src/lib/libidmap/common/idmap_impl.h | 26 +-- usr/src/lib/libidmap/common/idmap_priv.h | 20 +- usr/src/lib/libidmap/common/mapfile-vers | 2 - usr/src/lib/libidmap/common/utils.c | 237 ++++++++++++++++++--- usr/src/lib/libsec/common/acltext.c | 9 +- usr/src/lib/libsec/common/aclutils.c | 6 +- usr/src/lib/libzfs/common/libzfs_dataset.c | 7 +- usr/src/lib/nsswitch/ad/common/ad_common.h | 4 +- usr/src/lib/nsswitch/ad/common/getgrent.c | 16 +- usr/src/lib/nsswitch/ad/common/getpwnam.c | 36 +--- usr/src/lib/nsswitch/ad/common/getspent.c | 10 +- usr/src/lib/smbsrv/libmlsvc/common/dssetup_clnt.c | 20 +- usr/src/lib/smbsrv/libmlsvc/common/libmlsvc.h | 2 +- usr/src/lib/smbsrv/libmlsvc/common/mapfile-vers | 1 + usr/src/lib/smbsrv/libmlsvc/common/mlsvc_util.c | 9 +- usr/src/lib/smbsrv/libmlsvc/common/netr_logon.c | 19 +- usr/src/lib/smbsrv/libmlsvc/common/smb_logon.c | 29 ++- usr/src/lib/smbsrv/libmlsvc/common/spoolss_svc.c | 8 +- usr/src/lib/smbsrv/libsmb/common/smb_idmap.c | 73 +------ usr/src/lib/smbsrv/libsmb/common/smb_sd.c | 16 +- usr/src/uts/common/fs/smbsrv/smb_ofile.c | 1 + usr/src/uts/common/fs/smbsrv/smb_oplock.c | 65 +++--- usr/src/uts/common/smbsrv/smb_ktypes.h | 3 + 34 files changed, 596 insertions(+), 772 deletions(-) diff --git a/usr/src/cmd/idmap/idmap/idmap.c b/usr/src/cmd/idmap/idmap/idmap.c index 1c05e3d76a..57011eb4dc 100644 --- a/usr/src/cmd/idmap/idmap/idmap.c +++ b/usr/src/cmd/idmap/idmap/idmap.c @@ -214,7 +214,6 @@ struct pos_sds { static struct pos_sds *positions; /* Handles for idmap_api batch */ -static idmap_handle_t *handle = NULL; static idmap_udt_handle_t *udt = NULL; typedef struct { @@ -472,61 +471,17 @@ do_help(flag_t *f, int argc, char **argv, cmd_pos_t *pos) return (0); } -/* Initialization of the idmap api batch */ -static int -init_batch() -{ - idmap_stat stat; - - stat = idmap_init(&handle); - if (stat != IDMAP_SUCCESS) { - print_error(NULL, - gettext("Connection not established (%s)\n"), - idmap_stat2string(NULL, stat)); - handle = NULL; - return (-1); - } - - return (0); -} - -/* Initialization of the libidmap API (idmap help doesn't run that) */ -static int -init_command() -{ - if (batch_mode) - return (0); - - return (init_batch()); -} - -/* Finalization of the libidmap API */ -static void -fini_command() -{ - if (batch_mode) - return; - - if (handle != NULL) { - (void) idmap_fini(handle); - handle = NULL; - } -} - /* Initialization of the commands which perform write operations */ static int init_udt_batch() { idmap_stat stat; - if (init_batch()) - return (-1); - - stat = idmap_udt_create(handle, &udt); + stat = idmap_udt_create(&udt); if (stat != IDMAP_SUCCESS) { print_error(NULL, gettext("Error initiating transaction (%s)"), - idmap_stat2string(handle, stat)); + idmap_stat2string(stat)); return (-1); } @@ -577,7 +532,7 @@ fini_udt_command(int ok, cmd_pos_t *pos) if (stat1 != IDMAP_SUCCESS) { print_error(NULL, gettext("Error diagnosing transaction (%s)\n"), - idmap_stat2string(handle, stat1)); + idmap_stat2string(stat1)); goto out; } @@ -589,7 +544,7 @@ fini_udt_command(int ok, cmd_pos_t *pos) print_error(reported_pos, gettext("Error commiting transaction (%s)\n"), - idmap_stat2string(handle, stat)); + idmap_stat2string(stat)); } out: @@ -668,10 +623,6 @@ init_nm_command(char *user, char *passwd, char *auth, char *windomain, { idmap_stat stat; - if (!batch_mode) - if (init_batch() < 0) - return (-1); - if (namemaps.handle != NULL && ( strcmp_null(user, namemaps.user) != 0 || strcmp_null(passwd, namemaps.passwd) != 0 || @@ -682,13 +633,13 @@ init_nm_command(char *user, char *passwd, char *auth, char *windomain, } if (namemaps.handle == NULL) { - stat = idmap_init_namemaps(handle, &namemaps.handle, user, + stat = idmap_init_namemaps(&namemaps.handle, user, passwd, auth, windomain, direction); if (stat != IDMAP_SUCCESS) { print_error(pos, gettext("Error: could not perform directory-based " "name mapping operation (%s)"), - idmap_stat2string(handle, stat)); + idmap_stat2string(stat)); namemaps_free(); return (-1); } @@ -1597,9 +1548,6 @@ do_dump(flag_t *f, int argc, char **argv, cmd_pos_t *pos) int flag = 0; idmap_info info; - if (init_command()) - return (-1); - ph = print_mapping_init(f[n_FLAG] != NULL ? MAPPING_NAME : MAPPING_ID, stdout); if (ph == NULL) @@ -1608,11 +1556,11 @@ do_dump(flag_t *f, int argc, char **argv, cmd_pos_t *pos) if (f[v_FLAG] != NULL) flag = IDMAP_REQ_FLG_MAPPING_INFO; - stat = idmap_iter_mappings(handle, &ihandle, flag); + stat = idmap_iter_mappings(&ihandle, flag); if (stat < 0) { print_error(pos, gettext("Iteration handle not obtained (%s)\n"), - idmap_stat2string(handle, stat)); + idmap_stat2string(stat)); rc = -1; goto cleanup; } @@ -1646,7 +1594,7 @@ do_dump(flag_t *f, int argc, char **argv, cmd_pos_t *pos) if (stat < 0 && stat != IDMAP_ERR_NOTFOUND) { print_error(pos, gettext("Error during iteration (%s)\n"), - idmap_stat2string(handle, stat)); + idmap_stat2string(stat)); rc = -1; goto cleanup; } @@ -1655,7 +1603,6 @@ do_dump(flag_t *f, int argc, char **argv, cmd_pos_t *pos) cleanup: (void) print_mapping_fini(ph); - fini_command(); return (rc); } @@ -2167,7 +2114,7 @@ flush_nm(boolean_t is_user, cmd_pos_t *pos) print_error(pos, is_user ? gettext("Unable to flush users (%s).\n") : gettext("Unable to flush groups (%s).\n"), - idmap_stat2string(handle, stat)); + idmap_stat2string(stat)); return (-1); } @@ -2257,7 +2204,7 @@ do_import(flag_t *f, int argc, char **argv, cmd_pos_t *pos) if (stat < 0) { print_error(&pos2, gettext("Transaction error (%s)\n"), - idmap_stat2string(handle, stat)); + idmap_stat2string(stat)); rc = -1; } @@ -2299,11 +2246,11 @@ list_name_mappings(format_t format, FILE *fi) boolean_t is_wuser; print_handle_t *ph; - stat = idmap_iter_namerules(handle, NULL, 0, 0, NULL, NULL, &ihandle); + stat = idmap_iter_namerules(NULL, 0, 0, NULL, NULL, &ihandle); if (stat < 0) { print_error(NULL, gettext("Iteration handle not obtained (%s)\n"), - idmap_stat2string(handle, stat)); + idmap_stat2string(stat)); idmap_iter_destroy(ihandle); return (-1); } @@ -2337,7 +2284,7 @@ list_name_mappings(format_t format, FILE *fi) if (stat < 0 && stat != IDMAP_ERR_NOTFOUND) { print_error(NULL, gettext("Error during iteration (%s)\n"), - idmap_stat2string(handle, stat)); + idmap_stat2string(stat)); idmap_iter_destroy(ihandle); return (-1); } @@ -2370,16 +2317,9 @@ do_export(flag_t *f, int argc, char **argv, cmd_pos_t *pos) } } - if (init_command() < 0) { - rc = -1; - goto cleanup; - } - /* List the requested types: */ rc = list_name_mappings(format, fi); - fini_command(); - cleanup: if (fi != NULL && fi != stdout) (void) fclose(fi); @@ -2393,14 +2333,9 @@ do_list_name_mappings(flag_t *f, int argc, char **argv, cmd_pos_t *pos) { int rc; - if (init_command()) { - return (-1); - } - /* List the requested types: */ rc = list_name_mappings(DEFAULT_FORMAT, stdout); - fini_command(); return (rc); } @@ -2707,7 +2642,7 @@ do_add_name_mapping(flag_t *f, int argc, char **argv, cmd_pos_t *pos) if (stat != IDMAP_SUCCESS) { print_error(pos, gettext("Mapping not created (%s)\n"), - idmap_stat2string(handle, stat)); + idmap_stat2string(stat)); rc = -1; } @@ -2814,7 +2749,7 @@ do_remove_name_mapping(flag_t *f, int argc, char **argv, cmd_pos_t *pos) if (stat != IDMAP_SUCCESS) { print_error(pos, gettext("Mapping not deleted (%s)\n"), - idmap_stat2string(handle, stat)); + idmap_stat2string(stat)); rc = -1; break; } @@ -2849,18 +2784,14 @@ do_flush(flag_t *f, int argc, char **argv, cmd_pos_t *pos) else op = IDMAP_FLUSH_EXPIRE; - if (init_command()) - return (-1); - - stat = idmap_flush(handle, op); + stat = idmap_flush(op); if (stat != IDMAP_SUCCESS) { print_error(pos, gettext("%s\n"), - idmap_stat2string(handle, stat)); + idmap_stat2string(stat)); rc = -1; } - fini_command(); return (rc); } @@ -2968,9 +2899,6 @@ do_show_mapping(flag_t *f, int argc, char **argv, cmd_pos_t *pos) if (f[V_FLAG] != NULL) flag |= IDMAP_REQ_FLG_TRACE; - if (init_command()) - return (-1); - nm = name_mapping_init(); if (nm == NULL) goto cleanup; @@ -3032,7 +2960,7 @@ do_show_mapping(flag_t *f, int argc, char **argv, cmd_pos_t *pos) type_from == TYPE_GSID || type_from == TYPE_USID || type_to == TYPE_GSID || type_to == TYPE_USID) { if (type_from & IS_WIN) { - map_stat = idmap_get_w2u_mapping(handle, + map_stat = idmap_get_w2u_mapping( nm->sidprefix, &nm->rid, nm->winname, @@ -3044,7 +2972,7 @@ do_show_mapping(flag_t *f, int argc, char **argv, cmd_pos_t *pos) &nm->direction, &info); } else { - map_stat = idmap_get_u2w_mapping(handle, + map_stat = idmap_get_u2w_mapping( &nm->pid, nm->unixname, flag, @@ -3067,12 +2995,12 @@ do_show_mapping(flag_t *f, int argc, char **argv, cmd_pos_t *pos) /* Create an in-memory structure for all the batch: */ - stat = idmap_get_create(handle, &ghandle); + stat = idmap_get_create(&ghandle); if (stat != IDMAP_SUCCESS) { print_error(pos, gettext("Unable to create handle for communicating" " with idmapd(1M) (%s)\n"), - idmap_stat2string(handle, stat)); + idmap_stat2string(stat)); idmap_get_destroy(ghandle); goto cleanup; } @@ -3129,7 +3057,7 @@ do_show_mapping(flag_t *f, int argc, char **argv, cmd_pos_t *pos) if (stat < 0) { print_error(pos, gettext("Request for %.3s not sent (%s)\n"), - argv[0], idmap_stat2string(handle, stat)); + argv[0], idmap_stat2string(stat)); idmap_get_destroy(ghandle); goto cleanup; } @@ -3140,7 +3068,7 @@ do_show_mapping(flag_t *f, int argc, char **argv, cmd_pos_t *pos) print_error(pos, gettext("Mappings not obtained because of" " RPC problem (%s)\n"), - idmap_stat2string(handle, stat)); + idmap_stat2string(stat)); idmap_get_destroy(ghandle); goto cleanup; } @@ -3193,7 +3121,7 @@ do_show_mapping(flag_t *f, int argc, char **argv, cmd_pos_t *pos) errormsg: if (map_stat < 0) { print_error(pos, gettext("Error:\t%s\n"), - idmap_stat2string(handle, map_stat)); + idmap_stat2string(map_stat)); print_error_info(&info); } else { print_info(&info); @@ -3203,7 +3131,6 @@ errormsg: cleanup: if (nm != NULL) name_mapping_fini(nm); - fini_command(); return (stat < 0 || map_stat < 0 ? -1 : 0); } @@ -3342,7 +3269,7 @@ do_set_namemap(flag_t *f, int argc, char **argv, cmd_pos_t *pos) if (stat != IDMAP_SUCCESS) { print_error(pos, gettext("Failed to set namemap (%s).\n"), - idmap_stat2string(NULL, stat)); + idmap_stat2string(stat)); } if (passwd != NULL) { @@ -3425,7 +3352,7 @@ do_unset_namemap(flag_t *f, int argc, char **argv, cmd_pos_t *pos) if (stat != IDMAP_SUCCESS) { print_error(pos, gettext("Failed to unset namemap (%s).\n"), - idmap_stat2string(NULL, stat)); + idmap_stat2string(stat)); } cleanup: @@ -3498,7 +3425,7 @@ do_get_namemap(flag_t *f, int argc, char **argv, cmd_pos_t *pos) if (stat != IDMAP_SUCCESS) { print_error(pos, gettext("Failed to get namemap info (%s).\n"), - idmap_stat2string(NULL, stat)); + idmap_stat2string(stat)); goto cleanup; } @@ -3617,8 +3544,6 @@ main(int argc, char *argv[]) fini_nm_command(); } - fini_command(); - (void) engine_fini(); return (rc == 0 ? 0 : 1); } diff --git a/usr/src/cmd/idmap/idmap/namemaps.c b/usr/src/cmd/idmap/idmap/namemaps.c index 53c89f1554..c906bfeaa3 100644 --- a/usr/src/cmd/idmap/idmap/namemaps.c +++ b/usr/src/cmd/idmap/idmap/namemaps.c @@ -351,7 +351,7 @@ idmap_fini_namemaps(idmap_nm_handle_t *p) idmap_stat -idmap_init_namemaps(idmap_handle_t *handle, idmap_nm_handle_t **adh, +idmap_init_namemaps(idmap_nm_handle_t **adh, char *user, char *passwd, char *auth, char *windomain, int direction) { @@ -362,40 +362,40 @@ idmap_init_namemaps(idmap_handle_t *handle, idmap_nm_handle_t **adh, if (p == NULL) return (IDMAP_ERR_MEMORY); - rc = idmap_get_prop_str(handle, PROP_DEFAULT_DOMAIN, + rc = idmap_get_prop_str(PROP_DEFAULT_DOMAIN, &p->default_domain); if (rc != IDMAP_SUCCESS) { namemap_log( gettext("Error obtaining default domain from idmapd (%s)"), - idmap_stat2string(NULL, rc)); + idmap_stat2string(rc)); goto cleanup; } - rc = idmap_get_prop_str(handle, PROP_AD_UNIXUSER_ATTR, + rc = idmap_get_prop_str(PROP_AD_UNIXUSER_ATTR, &p->ad_unixuser_attr); if (rc != IDMAP_SUCCESS) { namemap_log( gettext("Error obtaining AD unixuser attribute (%s)"), - idmap_stat2string(NULL, rc)); + idmap_stat2string(rc)); goto cleanup; } - rc = idmap_get_prop_str(handle, PROP_AD_UNIXGROUP_ATTR, + rc = idmap_get_prop_str(PROP_AD_UNIXGROUP_ATTR, &p->ad_unixgroup_attr); if (rc != IDMAP_SUCCESS) { namemap_log( gettext("Error obtaining AD unixgroup attribute (%s)"), - idmap_stat2string(NULL, rc)); + idmap_stat2string(rc)); goto cleanup; } - rc = idmap_get_prop_str(handle, PROP_NLDAP_WINNAME_ATTR, + rc = idmap_get_prop_str(PROP_NLDAP_WINNAME_ATTR, &p->nldap_winname_attr); if (rc != IDMAP_SUCCESS) { namemap_log( gettext("Error obtaining AD unixgroup attribute (%s)"), - idmap_stat2string(NULL, rc)); + idmap_stat2string(rc)); goto cleanup; } diff --git a/usr/src/cmd/idmap/idmap/namemaps.h b/usr/src/cmd/idmap/idmap/namemaps.h index 4587406d6c..55c21d385c 100644 --- a/usr/src/cmd/idmap/idmap/namemaps.h +++ b/usr/src/cmd/idmap/idmap/namemaps.h @@ -52,7 +52,7 @@ extern idmap_stat idmap_get_namemap(idmap_nm_handle_t *p, int *, char **, extern void idmap_fini_namemaps(idmap_nm_handle_t *); -extern idmap_stat idmap_init_namemaps(idmap_handle_t *, idmap_nm_handle_t **, +extern idmap_stat idmap_init_namemaps(idmap_nm_handle_t **, char *, char *, char *, char *, int); #ifdef __cplusplus diff --git a/usr/src/cmd/idmap/idmapd/idmapd.h b/usr/src/cmd/idmap/idmapd/idmapd.h index 4e59ee49ae..5eab130684 100644 --- a/usr/src/cmd/idmap/idmapd/idmapd.h +++ b/usr/src/cmd/idmap/idmapd/idmapd.h @@ -142,25 +142,28 @@ typedef struct lookup_state { } lookup_state_t; #define NLDAP_OR_MIXED(nm) \ - (nm == IDMAP_NM_NLDAP || nm == IDMAP_NM_MIXED) + ((nm) == IDMAP_NM_NLDAP || (nm) == IDMAP_NM_MIXED) #define AD_OR_MIXED(nm) \ - (nm == IDMAP_NM_AD || nm == IDMAP_NM_MIXED) + ((nm) == IDMAP_NM_AD || (nm) == IDMAP_NM_MIXED) + +#define PID_UID_OR_UNKNOWN(pidtype) \ + ((pidtype) == IDMAP_UID || (pidtype) == IDMAP_POSIXID) +#define PID_GID_OR_UNKNOWN(pidtype) \ + ((pidtype) == IDMAP_GID || (pidtype) == IDMAP_POSIXID) #define NLDAP_OR_MIXED_MODE(pidtype, ls) \ - ((pidtype == IDMAP_UID && NLDAP_OR_MIXED(ls->nm_siduid)) || \ - (pidtype == IDMAP_GID && NLDAP_OR_MIXED(ls->nm_sidgid))) + (NLDAP_MODE(pidtype, ls) || MIXED_MODE(pidtype, ls)) #define AD_OR_MIXED_MODE(pidtype, ls)\ - ((pidtype == IDMAP_UID && AD_OR_MIXED(ls->nm_siduid)) || \ - (pidtype == IDMAP_GID && AD_OR_MIXED(ls->nm_sidgid))) + (AD_MODE(pidtype, ls) || MIXED_MODE(pidtype, ls)) #define NLDAP_MODE(pidtype, ls) \ - ((pidtype == IDMAP_UID && ls->nm_siduid == IDMAP_NM_NLDAP) || \ - (pidtype == IDMAP_GID && ls->nm_sidgid == IDMAP_NM_NLDAP)) + ((PID_UID_OR_UNKNOWN(pidtype) && (ls)->nm_siduid == IDMAP_NM_NLDAP) || \ + (PID_GID_OR_UNKNOWN(pidtype) && (ls)->nm_sidgid == IDMAP_NM_NLDAP)) #define AD_MODE(pidtype, ls) \ - ((pidtype == IDMAP_UID && ls->nm_siduid == IDMAP_NM_AD) || \ - (pidtype == IDMAP_GID && ls->nm_sidgid == IDMAP_NM_AD)) + ((PID_UID_OR_UNKNOWN(pidtype) && (ls)->nm_siduid == IDMAP_NM_AD) || \ + (PID_GID_OR_UNKNOWN(pidtype) && (ls)->nm_sidgid == IDMAP_NM_AD)) #define MIXED_MODE(pidtype, ls) \ - ((pidtype == IDMAP_UID && ls->nm_siduid == IDMAP_NM_MIXED) || \ - (pidtype == IDMAP_GID && ls->nm_sidgid == IDMAP_NM_MIXED)) + ((PID_UID_OR_UNKNOWN(pidtype) && (ls)->nm_siduid == IDMAP_NM_MIXED) || \ + (PID_GID_OR_UNKNOWN(pidtype) && (ls)->nm_sidgid == IDMAP_NM_MIXED)) typedef struct list_cb_data { diff --git a/usr/src/cmd/smbsrv/smbd/server.xml b/usr/src/cmd/smbsrv/smbd/server.xml index e5c45813c6..9889ea533a 100644 --- a/usr/src/cmd/smbsrv/smbd/server.xml +++ b/usr/src/cmd/smbsrv/smbd/server.xml @@ -64,7 +64,7 @@ file. diff --git a/usr/src/cmd/smbsrv/smbd/smbd.h b/usr/src/cmd/smbsrv/smbd/smbd.h index 00fa2f5ca7..cd17d19af2 100644 --- a/usr/src/cmd/smbsrv/smbd/smbd.h +++ b/usr/src/cmd/smbsrv/smbd/smbd.h @@ -45,14 +45,14 @@ void smbd_share_stop(void); int smbd_nicmon_start(const char *); void smbd_nicmon_stop(void); int smbd_nicmon_refresh(void); -boolean_t smbd_set_netlogon_cred(void); -int smbd_locate_dc_start(void); +int smbd_dc_monitor_init(void); smb_token_t *smbd_user_auth_logon(smb_logon_t *); void smbd_user_nonauth_logon(uint32_t); void smbd_user_auth_logoff(uint32_t); uint32_t smbd_join(smb_joininfo_t *); void smbd_set_secmode(int); boolean_t smbd_online(void); +void smbd_online_wait(const char *); int smbd_vss_get_count(const char *, uint32_t *); void smbd_vss_get_snapshots(const char *, uint32_t, uint32_t *, @@ -75,6 +75,10 @@ typedef struct smbd { int s_door_srv; int s_door_opipe; int s_secmode; /* Current security mode */ + pthread_t s_refresh_tid; + pthread_t s_localtime_tid; + pthread_t s_spool_tid; + pthread_t s_dc_monitor_tid; boolean_t s_nbt_listener_running; boolean_t s_tcp_listener_running; pthread_t s_nbt_listener_id; diff --git a/usr/src/cmd/smbsrv/smbd/smbd_join.c b/usr/src/cmd/smbsrv/smbd/smbd_join.c index f0bbf9b18c..d0030a8c0a 100644 --- a/usr/src/cmd/smbsrv/smbd/smbd_join.c +++ b/usr/src/cmd/smbsrv/smbd/smbd_join.c @@ -37,19 +37,128 @@ #include #include "smbd.h" +#define SMBD_DC_MONITOR_ATTEMPTS 3 +#define SMBD_DC_MONITOR_RETRY_INTERVAL 3 /* seconds */ +#define SMBD_DC_MONITOR_INTERVAL 60 /* seconds */ -/* - * This is a short-lived thread that triggers the initial DC discovery - * at startup. - */ -static pthread_t smb_locate_dc_thr; +extern smbd_t smbd; -static void *smbd_locate_dc_thread(void *); +static void *smbd_dc_monitor(void *); +static void smbd_dc_update(void); +static boolean_t smbd_set_netlogon_cred(void); static int smbd_get_kpasswd_srv(char *, size_t); static uint32_t smbd_join_workgroup(smb_joininfo_t *); static uint32_t smbd_join_domain(smb_joininfo_t *); /* + * Launch the DC discovery and monitor thread. + */ +int +smbd_dc_monitor_init(void) +{ + pthread_attr_t attr; + int rc; + + smb_ads_init(); + + if (smbd.s_secmode != SMB_SECMODE_DOMAIN) + return (0); + + (void) pthread_attr_init(&attr); + (void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + rc = pthread_create(&smbd.s_dc_monitor_tid, &attr, smbd_dc_monitor, + NULL); + (void) pthread_attr_destroy(&attr); + return (rc); +} + +/*ARGSUSED*/ +static void * +smbd_dc_monitor(void *arg) +{ + boolean_t ds_not_responding = B_FALSE; + int i; + + smbd_dc_update(); + smbd_online_wait("smbd_dc_monitor"); + + while (smbd_online()) { + (void) sleep(SMBD_DC_MONITOR_INTERVAL); + + for (i = 0; i < SMBD_DC_MONITOR_ATTEMPTS; ++i) { + if (dssetup_check_service() == 0) { + ds_not_responding = B_FALSE; + break; + } + + ds_not_responding = B_TRUE; + (void) sleep(SMBD_DC_MONITOR_RETRY_INTERVAL); + } + + if (ds_not_responding) { + smb_log(smbd.s_loghd, LOG_NOTICE, + "smbd_dc_monitor: domain service not responding"); + + smb_ads_refresh(); + smbd_dc_update(); + } + } + + smbd.s_dc_monitor_tid = 0; + return (NULL); +} + +/* + * Locate a domain controller in the current resource domain and Update + * the Netlogon credential chain. + * + * The domain configuration will be updated upon successful DC discovery. + */ +static void +smbd_dc_update(void) +{ + char domain[MAXHOSTNAMELEN]; + smb_domainex_t info; + smb_domain_t *primary; + + + if (smb_getfqdomainname(domain, MAXHOSTNAMELEN) != 0) { + (void) smb_getdomainname(domain, MAXHOSTNAMELEN); + (void) smb_strupr(domain); + } + + if (!smb_locate_dc(domain, "", &info)) { + smb_log(smbd.s_loghd, LOG_NOTICE, + "smbd_dc_update: %s: locate failed", domain); + } else { + primary = &info.d_primary; + + smb_config_setdomaininfo(primary->di_nbname, + primary->di_fqname, + primary->di_sid, + primary->di_u.di_dns.ddi_forest, + primary->di_u.di_dns.ddi_guid); + + smb_log(smbd.s_loghd, LOG_NOTICE, + "smbd_dc_update: %s: located %s", domain, info.d_dc); + } + + if (smbd_set_netlogon_cred()) { + /* + * Restart required because the domain changed + * or the credential chain setup failed. + */ + smb_log(smbd.s_loghd, LOG_NOTICE, + "smbd_dc_update: %s: smb/server restart required"); + + if (smb_smf_restart_service() != 0) + smb_log(smbd.s_loghd, LOG_ERR, + "restart failed: run 'svcs -xv smb/server'" + " for more information"); + } +} + +/* * smbd_join * * Joins the specified domain/workgroup. @@ -91,7 +200,7 @@ smbd_join(smb_joininfo_t *info) * If joining a new domain, the domain_name property must be set after a * successful credential chain setup. */ -boolean_t +static boolean_t smbd_set_netlogon_cred(void) { char kpasswd_srv[MAXHOSTNAMELEN]; @@ -103,9 +212,6 @@ smbd_set_netlogon_cred(void) smb_domainex_t dxi; smb_domain_t *di; - if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN) - return (B_FALSE); - if (smb_match_netlogon_seqnum()) return (B_FALSE); @@ -158,7 +264,7 @@ smbd_set_netlogon_cred(void) smb_ipc_commit(); if (mlsvc_netlogon(dxi.d_dc, di->di_nbname)) { - syslog(LOG_ERR, + syslog(LOG_NOTICE, "failed to establish NETLOGON credential chain"); return (B_TRUE); } else { @@ -175,64 +281,6 @@ smbd_set_netlogon_cred(void) } /* - * smbd_locate_dc_start() - * - * Initialization of the thread that triggers the initial DC discovery - * when SMB daemon starts up. - * Returns 0 on success, an error number if thread creation fails. - */ -int -smbd_locate_dc_start(void) -{ - pthread_attr_t tattr; - int rc; - - (void) pthread_attr_init(&tattr); - (void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED); - rc = pthread_create(&smb_locate_dc_thr, &tattr, smbd_locate_dc_thread, - NULL); - (void) pthread_attr_destroy(&tattr); - return (rc); -} - -/* - * smbd_locate_dc_thread() - * - * If necessary, set up Netlogon credential chain and locate a - * domain controller in the given resource domain. - * - * The domain configuration will be updated upon a successful DC discovery. - */ -/*ARGSUSED*/ -static void * -smbd_locate_dc_thread(void *arg) -{ - char domain[MAXHOSTNAMELEN]; - smb_domainex_t new_domain; - smb_domain_t *di; - - if (!smb_match_netlogon_seqnum()) { - (void) smbd_set_netlogon_cred(); - } else { - if (smb_getfqdomainname(domain, MAXHOSTNAMELEN) != 0) { - (void) smb_getdomainname(domain, MAXHOSTNAMELEN); - (void) smb_strupr(domain); - } - - if (smb_locate_dc(domain, "", &new_domain)) { - di = &new_domain.d_primary; - smb_config_setdomaininfo(di->di_nbname, di->di_fqname, - di->di_sid, - di->di_u.di_dns.ddi_forest, - di->di_u.di_dns.ddi_guid); - } - } - - return (NULL); -} - - -/* * Retrieve the kpasswd server from krb5.conf. * * Initialization of the locate dc thread. diff --git a/usr/src/cmd/smbsrv/smbd/smbd_main.c b/usr/src/cmd/smbsrv/smbd/smbd_main.c index 4278430694..3bca31d9a5 100644 --- a/usr/src/cmd/smbsrv/smbd/smbd_main.c +++ b/usr/src/cmd/smbsrv/smbd/smbd_main.c @@ -58,6 +58,7 @@ #include #include "smbd.h" +#define SMBD_ONLINE_WAIT_INTERVAL 10 #define SMB_CUPS_DOCNAME "generic_doc" #define DRV_DEVICE_PATH "/devices/pseudo/smbsrv@0:smbsrv" #define SMB_DBDIR "/var/smb" @@ -89,16 +90,15 @@ static int32_t smbd_gmtoff(void); static int smbd_localtime_init(void); static void *smbd_localtime_monitor(void *arg); -static pthread_t localtime_thr; +static int smbd_spool_init(void); +static void *smbd_spool_monitor(void *arg); static int smbd_spool_init(void); static void *smbd_spool_monitor(void *arg); -static pthread_t smbd_spool_thr; static int smbd_refresh_init(void); static void smbd_refresh_fini(void); static void *smbd_refresh_monitor(void *); -static void smbd_refresh_dc(void); static void *smbd_nbt_receiver(void *); static void *smbd_nbt_listener(void *); @@ -112,7 +112,6 @@ static int smbd_kernel_start(void); static void smbd_fatal_error(const char *); -static pthread_t refresh_thr; static pthread_cond_t refresh_cond; static pthread_mutex_t refresh_mutex; @@ -516,17 +515,16 @@ smbd_service_init(void) } } - smb_ads_init(); + if (smbd_dc_monitor_init() != 0) + smbd_report("DC monitor initialization failed %s", + strerror(errno)); + if (mlsvc_init() != 0) { smbd_report("msrpc initialization failed"); (void) mutex_unlock(&smbd_service_mutex); return (-1); } - if (smbd.s_secmode == SMB_SECMODE_DOMAIN) - if (smbd_locate_dc_start() != 0) - smbd_report("dc discovery failed %s", strerror(errno)); - smbd.s_door_srv = smbd_door_start(); smbd.s_door_opipe = smbd_opipe_start(); if (smbd.s_door_srv < 0 || smbd.s_door_opipe < 0) { @@ -623,7 +621,6 @@ smbd_service_fini(void) smb_pwd_fini(); smb_domain_fini(); mlsvc_fini(); - smb_ads_fini(); smb_netbios_stop(); smbd.s_initialized = B_FALSE; @@ -654,7 +651,8 @@ smbd_refresh_init() (void) pthread_attr_init(&tattr); (void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED); - rc = pthread_create(&refresh_thr, &tattr, smbd_refresh_monitor, 0); + rc = pthread_create(&smbd.s_refresh_tid, &tattr, smbd_refresh_monitor, + NULL); (void) pthread_attr_destroy(&tattr); return (rc); @@ -668,8 +666,8 @@ smbd_refresh_init() static void smbd_refresh_fini() { - if (pthread_self() != refresh_thr) { - (void) pthread_cancel(refresh_thr); + if (pthread_self() != smbd.s_refresh_tid) { + (void) pthread_cancel(smbd.s_refresh_tid); (void) pthread_cond_destroy(&refresh_cond); (void) pthread_mutex_destroy(&refresh_mutex); } @@ -722,28 +720,10 @@ smbd_refresh_monitor(void *arg) smbd_report("NIC monitor refresh failed"); smb_netbios_name_reconfig(); smb_browser_reconfig(); - smbd_refresh_dc(); dyndns_update_zones(); (void) mutex_unlock(&smbd_service_mutex); - if (smbd_set_netlogon_cred()) { - /* - * Restart required because the domain changed - * or the credential chain setup failed. - */ - if (smb_smf_restart_service() != 0) { - syslog(LOG_ERR, - "unable to restart smb/server. " - "Run 'svcs -xv smb/server' for more " - "information."); - smbd_service_fini(); - /*NOTREACHED*/ - } - - break; - } - if (!smbd.s_kbound) { if ((error = smbd_kernel_bind()) == 0) (void) smb_shr_load(); @@ -763,23 +743,6 @@ smbd_refresh_monitor(void *arg) return (NULL); } -/* - * Update DC information on a refresh. - */ -static void -smbd_refresh_dc(void) -{ - char fqdomain[MAXHOSTNAMELEN]; - if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN) - return; - - if (smb_getfqdomainname(fqdomain, MAXHOSTNAMELEN)) - return; - - if (!smb_locate_dc(fqdomain, "", NULL)) - smbd_report("DC refresh failed"); -} - void smbd_set_secmode(int secmode) { @@ -808,6 +771,26 @@ smbd_online(void) } /* + * Wait until the service is online. Provided for threads that + * should wait until the service has been fully initialized before + * they start performing operations. + */ +void +smbd_online_wait(const char *text) +{ + while (!smbd_online()) { + if (text != NULL) + smb_log(smbd.s_loghd, LOG_DEBUG, + "%s: waiting for online", text); + + (void) sleep(SMBD_ONLINE_WAIT_INTERVAL); + } + + if (text != NULL) + smb_log(smbd.s_loghd, LOG_DEBUG, "%s: online", text); +} + +/* * If the door has already been opened by another process (non-zero pid * in target), we assume that another smbd is already running. If there * is a race here, it will be caught later when smbsrv is opened because @@ -911,7 +894,8 @@ smbd_spool_init(void) (void) pthread_attr_init(&tattr); (void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED); - rc = pthread_create(&smbd_spool_thr, &tattr, smbd_spool_monitor, 0); + rc = pthread_create(&smbd.s_spool_tid, &tattr, smbd_spool_monitor, + NULL); (void) pthread_attr_destroy(&tattr); return (rc); @@ -936,6 +920,8 @@ smbd_spool_monitor(void *arg) smb_inaddr_t ipaddr; int error_retry_cnt = 5; + smbd_online_wait("smbd_spool_monitor"); + while (!smbd.s_shutting_down && (error_retry_cnt > 0)) { errno = 0; @@ -968,7 +954,8 @@ smbd_localtime_init(void) (void) pthread_attr_init(&tattr); (void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED); - rc = pthread_create(&localtime_thr, &tattr, smbd_localtime_monitor, 0); + rc = pthread_create(&smbd.s_localtime_tid, &tattr, + smbd_localtime_monitor, NULL); (void) pthread_attr_destroy(&tattr); return (rc); } @@ -992,6 +979,8 @@ smbd_localtime_monitor(void *arg) int timeout; int error; + smbd_online_wait("smbd_localtime_monitor"); + for (;;) { gmtoff = smbd_gmtoff(); diff --git a/usr/src/common/smbclnt/smbfs_ntacl.c b/usr/src/common/smbclnt/smbfs_ntacl.c index 47676da116..6780d891ee 100644 --- a/usr/src/common/smbclnt/smbfs_ntacl.c +++ b/usr/src/common/smbclnt/smbfs_ntacl.c @@ -20,8 +20,7 @@ */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. */ /* @@ -902,9 +901,6 @@ smbfs_acl_sd2zfs( gid_t own_gid = (gid_t)-1; i_ntacl_t *ntacl; i_ntace_t **ntacep; -#ifndef _KERNEL - idmap_handle_t *idmap_h = NULL; -#endif /* _KERNEL */ idmap_get_handle_t *idmap_gh = NULL; idmap_stat idms; @@ -961,12 +957,7 @@ smbfs_acl_sd2zfs( #ifdef _KERNEL idmap_gh = kidmap_get_create(curproc->p_zone); #else /* _KERNEL */ - idms = idmap_init(&idmap_h); - if (idms != IDMAP_SUCCESS) { - error = ENOTACTIVE; - goto errout; - } - idms = idmap_get_create(idmap_h, &idmap_gh); + idms = idmap_get_create(&idmap_gh); if (idms != IDMAP_SUCCESS) { error = ENOTACTIVE; goto errout; @@ -1147,8 +1138,6 @@ errout: #else /* _KERNEL */ if (idmap_gh != NULL) idmap_get_destroy(idmap_gh); - if (idmap_h != NULL) - (void) idmap_fini(idmap_h); #endif /* _KERNEL */ return (error); @@ -1440,9 +1429,6 @@ smbfs_acl_zfs2sd( i_ntsd_t *sd = NULL; i_ntacl_t *acl = NULL; i_ntace_t **acep = NULL; -#ifndef _KERNEL - idmap_handle_t *idmap_h = NULL; -#endif /* _KERNEL */ idmap_get_handle_t *idmap_gh = NULL; idmap_stat idms; @@ -1499,12 +1485,7 @@ smbfs_acl_zfs2sd( #ifdef _KERNEL idmap_gh = kidmap_get_create(curproc->p_zone); #else /* _KERNEL */ - idms = idmap_init(&idmap_h); - if (idms != IDMAP_SUCCESS) { - error = ENOTACTIVE; - goto errout; - } - idms = idmap_get_create(idmap_h, &idmap_gh); + idms = idmap_get_create(&idmap_gh); if (idms != IDMAP_SUCCESS) { error = ENOTACTIVE; goto errout; @@ -1719,8 +1700,6 @@ errout: #else /* _KERNEL */ if (idmap_gh != NULL) idmap_get_destroy(idmap_gh); - if (idmap_h != NULL) - (void) idmap_fini(idmap_h); #endif /* _KERNEL */ return (error); diff --git a/usr/src/lib/libidmap/common/idmap.h b/usr/src/lib/libidmap/common/idmap.h index 400f67c755..3a3af0d32c 100644 --- a/usr/src/lib/libidmap/common/idmap.h +++ b/usr/src/lib/libidmap/common/idmap.h @@ -46,9 +46,6 @@ typedef int32_t idmap_stat; typedef uint32_t idmap_rid_t; -/* Opaque client handle */ -typedef struct idmap_handle idmap_handle_t; - /* Opaque "get-mapping" handle */ typedef struct idmap_get_handle idmap_get_handle_t; @@ -58,14 +55,9 @@ typedef void (*idmap_logger_t)(int, const char *, ...); /* * Setup API */ -/* Create/Init handle for userland clients */ -extern idmap_stat idmap_init(idmap_handle_t **); - -/* Finalize/close handle */ -extern idmap_stat idmap_fini(idmap_handle_t *); /* Status code to string */ -extern const char *idmap_stat2string(idmap_handle_t *, idmap_stat); +extern const char *idmap_stat2string(idmap_stat); /* Free memory allocated by the API */ extern void idmap_free(void *); @@ -83,7 +75,7 @@ extern void idmap_free(void *); * API to batch SID to UID/GID mapping requests */ /* Create handle */ -extern idmap_stat idmap_get_create(idmap_handle_t *, idmap_get_handle_t **); +extern idmap_stat idmap_get_create(idmap_get_handle_t **); /* Given SID, get UID */ extern idmap_stat idmap_get_uidbysid(idmap_get_handle_t *, char *, diff --git a/usr/src/lib/libidmap/common/idmap_api.c b/usr/src/lib/libidmap/common/idmap_api.c index e31ff1ffc3..e3ae017357 100644 --- a/usr/src/lib/libidmap/common/idmap_api.c +++ b/usr/src/lib/libidmap/common/idmap_api.c @@ -38,7 +38,6 @@ #include #include #include -#include #include #include #include "idmap_impl.h" @@ -49,11 +48,7 @@ static struct timeval TIMEOUT = { 25, 0 }; static int idmap_stat2errno(idmap_stat); static idmap_stat idmap_strdupnull(char **, const char *); -#define __ITER_CREATE(itera, argu, handl, ityp)\ - if (handl == NULL) {\ - errno = EINVAL;\ - return (IDMAP_ERR_ARG);\ - }\ +#define __ITER_CREATE(itera, argu, ityp)\ itera = calloc(1, sizeof (*itera));\ if (itera == NULL) {\ errno = ENOMEM;\ @@ -65,7 +60,6 @@ static idmap_stat idmap_strdupnull(char **, const char *); errno = ENOMEM;\ return (IDMAP_ERR_MEMORY);\ }\ - itera->ih = handl;\ itera->type = ityp;\ itera->retcode = IDMAP_NEXT;\ itera->limit = 1024;\ @@ -105,136 +99,30 @@ idmap_free(void *ptr) } -#define MIN_STACK_NEEDS 65536 - -/* - * Create and Initialize idmap client handle for rpc/doors - * - * Output: - * handle - idmap handle - */ -idmap_stat -idmap_init(idmap_handle_t **handle) -{ - CLIENT *clnt = NULL; - struct idmap_handle *hptr; - uint_t sendsz = 0; - stack_t st; - - *handle = NULL; - hptr = (struct idmap_handle *)calloc(1, sizeof (*hptr)); - if (hptr == NULL) - return (IDMAP_ERR_MEMORY); - - /* - * clnt_door_call() alloca()s sendsz bytes (twice too, once for - * the call args buffer and once for the call result buffer), so - * we want to pick a sendsz that will be large enough, but not - * too large. - */ - if (stack_getbounds(&st) == 0) { - /* - * Estimate how much stack space is left; - * st.ss_sp is the top of stack. - */ - if ((char *)&sendsz < (char *)st.ss_sp) - /* stack grows up */ - sendsz = ((char *)st.ss_sp - (char *)&sendsz); - else - /* stack grows down */ - sendsz = ((char *)&sendsz - (char *)st.ss_sp); - - if (sendsz <= MIN_STACK_NEEDS) { - sendsz = 0; /* RPC call may fail */ - } else { - /* Leave 64Kb (just a guess) for our needs */ - sendsz -= MIN_STACK_NEEDS; - - /* Divide the stack space left by two */ - sendsz = RNDUP(sendsz / 2); - - /* Limit sendsz to 256KB */ - if (sendsz > IDMAP_MAX_DOOR_RPC) - sendsz = IDMAP_MAX_DOOR_RPC; - } - } - - clnt = clnt_door_create(IDMAP_PROG, IDMAP_V1, sendsz); - if (clnt == NULL) { - free(hptr); - return (IDMAP_ERR_RPC); - } - hptr->type = _IDMAP_HANDLE_RPC_DOORS; - hptr->privhandle = clnt; - *handle = hptr; - return (IDMAP_SUCCESS); -} - - -/* - * Finalize idmap handle - * - * Input: - * handle - idmap handle - */ -idmap_stat -idmap_fini(idmap_handle_t *handle) -{ - CLIENT *clnt; - struct idmap_handle *hptr; - - if (handle == NULL) - return (IDMAP_SUCCESS); - - hptr = (struct idmap_handle *)handle; - - switch (hptr->type) { - case _IDMAP_HANDLE_RPC_DOORS: - clnt = (CLIENT *)hptr->privhandle; - if (clnt) { - if (clnt->cl_auth) - auth_destroy(clnt->cl_auth); - clnt_destroy(clnt); - } - break; - default: - break; - } - free(hptr); - return (IDMAP_SUCCESS); -} - - static idmap_stat -idmap_get_prop(idmap_handle_t *handle, idmap_prop_type pr, idmap_prop_res *res) +idmap_get_prop(idmap_prop_type pr, idmap_prop_res *res) { - CLIENT *clnt; - enum clnt_stat clntstat; - + idmap_stat retcode; (void) memset(res, 0, sizeof (*res)); - _IDMAP_GET_CLIENT_HANDLE(handle, clnt); - clntstat = clnt_call(clnt, IDMAP_GET_PROP, + retcode = _idmap_clnt_call(IDMAP_GET_PROP, (xdrproc_t)xdr_idmap_prop_type, (caddr_t)&pr, (xdrproc_t)xdr_idmap_prop_res, (caddr_t)res, TIMEOUT); - - if (clntstat != RPC_SUCCESS) { - return (_idmap_rpc2stat(clnt)); - } + if (retcode != IDMAP_SUCCESS) + return (retcode); return (res->retcode); /* This might not be IDMAP_SUCCESS! */ } idmap_stat -idmap_get_prop_ds(idmap_handle_t *handle, idmap_prop_type pr, - idmap_ad_disc_ds_t *dc) +idmap_get_prop_ds(idmap_prop_type pr, idmap_ad_disc_ds_t *dc) { idmap_prop_res res; idmap_stat rc = IDMAP_SUCCESS; - rc = idmap_get_prop(handle, pr, &res); + rc = idmap_get_prop(pr, &res); if (rc < 0) return (rc); @@ -254,12 +142,12 @@ idmap_get_prop_ds(idmap_handle_t *handle, idmap_prop_type pr, * otherwise IDMAP_SUCCESS is returned. */ idmap_stat -idmap_get_prop_str(idmap_handle_t *handle, idmap_prop_type pr, char **str) +idmap_get_prop_str(idmap_prop_type pr, char **str) { idmap_prop_res res; idmap_stat rc = IDMAP_SUCCESS; - rc = idmap_get_prop(handle, pr, &res); + rc = idmap_get_prop(pr, &res); if (rc < 0) return (rc); @@ -274,11 +162,11 @@ idmap_get_prop_str(idmap_handle_t *handle, idmap_prop_type pr, char **str) * udthandle - update handle */ idmap_stat -idmap_udt_create(idmap_handle_t *handle, idmap_udt_handle_t **udthandle) +idmap_udt_create(idmap_udt_handle_t **udthandle) { idmap_udt_handle_t *tmp; - if (handle == NULL || udthandle == NULL) { + if (udthandle == NULL) { errno = EINVAL; return (IDMAP_ERR_ARG); } @@ -287,7 +175,6 @@ idmap_udt_create(idmap_handle_t *handle, idmap_udt_handle_t **udthandle) return (IDMAP_ERR_MEMORY); } - tmp->ih = handle; *udthandle = tmp; return (IDMAP_SUCCESS); } @@ -306,8 +193,6 @@ idmap_udt_create(idmap_handle_t *handle, idmap_udt_handle_t **udthandle) idmap_stat idmap_udt_commit(idmap_udt_handle_t *udthandle) { - CLIENT *clnt; - enum clnt_stat clntstat; idmap_update_res res; idmap_stat retcode; @@ -318,16 +203,12 @@ idmap_udt_commit(idmap_udt_handle_t *udthandle) (void) memset(&res, 0, sizeof (res)); - _IDMAP_GET_CLIENT_HANDLE(udthandle->ih, clnt); - clntstat = clnt_call(clnt, IDMAP_UPDATE, + retcode = _idmap_clnt_call(IDMAP_UPDATE, (xdrproc_t)xdr_idmap_update_batch, (caddr_t)&udthandle->batch, (xdrproc_t)xdr_idmap_update_res, (caddr_t)&res, TIMEOUT); - - if (clntstat != RPC_SUCCESS) { - retcode = _idmap_rpc2stat(clnt); + if (retcode != IDMAP_SUCCESS) goto out; - } retcode = udthandle->commit_stat = res.retcode; udthandle->error_index = res.error_index; @@ -692,7 +573,7 @@ idmap_iter_set_limit(idmap_iter_t *iter, uint64_t limit) * iter - iterator */ idmap_stat -idmap_iter_namerules(idmap_handle_t *handle, const char *windomain, +idmap_iter_namerules(const char *windomain, boolean_t is_user, boolean_t is_wuser, const char *winname, const char *unixname, idmap_iter_t **iter) { @@ -702,7 +583,7 @@ idmap_iter_namerules(idmap_handle_t *handle, const char *windomain, idmap_namerule *rule; idmap_retcode retcode; - __ITER_CREATE(tmpiter, arg, handle, IDMAP_LIST_NAMERULES); + __ITER_CREATE(tmpiter, arg, IDMAP_LIST_NAMERULES); rule = &arg->rule; rule->is_user = is_user; @@ -847,12 +728,12 @@ errout: * iter - iterator */ idmap_stat -idmap_iter_mappings(idmap_handle_t *handle, idmap_iter_t **iter, int flag) +idmap_iter_mappings(idmap_iter_t **iter, int flag) { idmap_iter_t *tmpiter; idmap_list_mappings_1_argument *arg = NULL; - __ITER_CREATE(tmpiter, arg, handle, IDMAP_LIST_MAPPINGS); + __ITER_CREATE(tmpiter, arg, IDMAP_LIST_MAPPINGS); arg->flag = flag; *iter = tmpiter; @@ -1055,23 +936,16 @@ idmap_iter_destroy(idmap_iter_t *iter) * gh - "get mapping" handle */ idmap_stat -idmap_get_create(idmap_handle_t *handle, idmap_get_handle_t **gh) +idmap_get_create(idmap_get_handle_t **gh) { idmap_get_handle_t *tmp; - /* sanity checks */ - if (handle == NULL || gh == NULL) { - errno = EINVAL; - return (IDMAP_ERR_ARG); - } - /* allocate the handle */ if ((tmp = calloc(1, sizeof (*tmp))) == NULL) { errno = ENOMEM; return (IDMAP_ERR_MEMORY); } - tmp->ih = handle; *gh = tmp; return (IDMAP_SUCCESS); } @@ -1557,8 +1431,6 @@ errout: idmap_stat idmap_get_mappings(idmap_get_handle_t *gh) { - CLIENT *clnt; - enum clnt_stat clntstat; idmap_retcode retcode; idmap_ids_res res; idmap_id *res_id; @@ -1570,17 +1442,15 @@ idmap_get_mappings(idmap_get_handle_t *gh) errno = EINVAL; return (IDMAP_ERR_ARG); } - _IDMAP_GET_CLIENT_HANDLE(gh->ih, clnt); (void) memset(&res, 0, sizeof (idmap_ids_res)); - clntstat = clnt_call(clnt, IDMAP_GET_MAPPED_IDS, + retcode = _idmap_clnt_call(IDMAP_GET_MAPPED_IDS, (xdrproc_t)xdr_idmap_mapping_batch, (caddr_t)&gh->batch, (xdrproc_t)xdr_idmap_ids_res, (caddr_t)&res, TIMEOUT); - if (clntstat != RPC_SUCCESS) { - retcode = _idmap_rpc2stat(clnt); + if (retcode != IDMAP_SUCCESS) { goto out; } if (res.retcode != IDMAP_SUCCESS) { @@ -1726,25 +1596,16 @@ idmap_get_destroy(idmap_get_handle_t *gh) * Get windows to unix mapping */ idmap_stat -idmap_get_w2u_mapping(idmap_handle_t *handle, +idmap_get_w2u_mapping( const char *sidprefix, idmap_rid_t *rid, const char *winname, const char *windomain, int flag, int *is_user, int *is_wuser, uid_t *pid, char **unixname, int *direction, idmap_info *info) { - CLIENT *clnt; - enum clnt_stat clntstat; idmap_mapping request, *mapping; idmap_mappings_res result; idmap_retcode retcode, rc; - if (handle == NULL) { - errno = EINVAL; - return (IDMAP_ERR_ARG); - } - - _IDMAP_GET_CLIENT_HANDLE(handle, clnt); - (void) memset(&request, 0, sizeof (request)); (void) memset(&result, 0, sizeof (result)); @@ -1789,13 +1650,13 @@ idmap_get_w2u_mapping(idmap_handle_t *handle, else request.id1.idtype = IDMAP_SID; - clntstat = clnt_call(clnt, IDMAP_GET_MAPPED_ID_BY_NAME, + retcode = _idmap_clnt_call(IDMAP_GET_MAPPED_ID_BY_NAME, (xdrproc_t)xdr_idmap_mapping, (caddr_t)&request, (xdrproc_t)xdr_idmap_mappings_res, (caddr_t)&result, TIMEOUT); - if (clntstat != RPC_SUCCESS) - return (_idmap_rpc2stat(clnt)); + if (retcode != IDMAP_SUCCESS) + return (retcode); retcode = result.retcode; @@ -1849,26 +1710,17 @@ out: * Get unix to windows mapping */ idmap_stat -idmap_get_u2w_mapping(idmap_handle_t *handle, +idmap_get_u2w_mapping( uid_t *pid, const char *unixname, int flag, int is_user, int *is_wuser, char **sidprefix, idmap_rid_t *rid, char **winname, char **windomain, int *direction, idmap_info *info) { - CLIENT *clnt; - enum clnt_stat clntstat; idmap_mapping request, *mapping; idmap_mappings_res result; idmap_retcode retcode, rc; - if (handle == NULL) { - errno = EINVAL; - return (IDMAP_ERR_ARG); - } - - _IDMAP_GET_CLIENT_HANDLE(handle, clnt); - if (sidprefix) *sidprefix = NULL; if (winname) @@ -1905,13 +1757,13 @@ idmap_get_u2w_mapping(idmap_handle_t *handle, else if (*is_wuser == 1) request.id2.idtype = IDMAP_USID; - clntstat = clnt_call(clnt, IDMAP_GET_MAPPED_ID_BY_NAME, + retcode = _idmap_clnt_call(IDMAP_GET_MAPPED_ID_BY_NAME, (xdrproc_t)xdr_idmap_mapping, (caddr_t)&request, (xdrproc_t)xdr_idmap_mappings_res, (caddr_t)&result, TIMEOUT); - if (clntstat != RPC_SUCCESS) - return (_idmap_rpc2stat(clnt)); + if (retcode != IDMAP_SUCCESS) + return (retcode); retcode = result.retcode; @@ -2060,9 +1912,8 @@ static stat_table_t stattable[] = { * Return Value: * human-readable localized description of idmap_stat */ -/* ARGSUSED */ const char * -idmap_stat2string(idmap_handle_t *handle, idmap_stat status) +idmap_stat2string(idmap_stat status) { int i; @@ -2258,7 +2109,6 @@ idmap_stat idmap_getuidbywinname(const char *name, const char *domain, int flag, uid_t *uid) { - idmap_handle_t *ih; idmap_retcode rc; int is_user = 1; int is_wuser = -1; @@ -2273,11 +2123,8 @@ idmap_getuidbywinname(const char *name, const char *domain, int flag, return (rc); } /* Get mapping */ - if ((rc = idmap_init(&ih)) != IDMAP_SUCCESS) - return (rc); - rc = idmap_get_w2u_mapping(ih, NULL, NULL, name, domain, flag, + rc = idmap_get_w2u_mapping(NULL, NULL, name, domain, flag, &is_user, &is_wuser, uid, NULL, &direction, NULL); - (void) idmap_fini(ih); if (rc == IDMAP_SUCCESS && (flag & IDMAP_REQ_FLG_USE_CACHE)) { /* If we have not got the domain don't store UID to winname */ @@ -2297,7 +2144,6 @@ idmap_stat idmap_getgidbywinname(const char *name, const char *domain, int flag, gid_t *gid) { - idmap_handle_t *ih; idmap_retcode rc; int is_user = 0; int is_wuser = -1; @@ -2313,11 +2159,8 @@ idmap_getgidbywinname(const char *name, const char *domain, int flag, } /* Get mapping */ - if ((rc = idmap_init(&ih)) != IDMAP_SUCCESS) - return (rc); - rc = idmap_get_w2u_mapping(ih, NULL, NULL, name, domain, flag, + rc = idmap_get_w2u_mapping(NULL, NULL, name, domain, flag, &is_user, &is_wuser, gid, NULL, &direction, NULL); - (void) idmap_fini(ih); if (rc == IDMAP_SUCCESS && (flag & IDMAP_REQ_FLG_USE_CACHE)) { /* If we have not got the domain don't store GID to winname */ @@ -2337,7 +2180,6 @@ static idmap_retcode idmap_getwinnamebypid(uid_t pid, int is_user, int flag, char **name, char **domain) { - idmap_handle_t *ih; idmap_retcode rc; int len; char *winname, *windomain; @@ -2360,11 +2202,8 @@ idmap_getwinnamebypid(uid_t pid, int is_user, int flag, char **name, } /* Get mapping */ - if ((rc = idmap_init(&ih)) != IDMAP_SUCCESS) - return (rc); - rc = idmap_get_u2w_mapping(ih, &pid, NULL, flag, is_user, NULL, + rc = idmap_get_u2w_mapping(&pid, NULL, flag, is_user, NULL, NULL, NULL, &winname, &windomain, &direction, NULL); - (void) idmap_fini(ih); /* Return on error */ if (rc != IDMAP_SUCCESS) @@ -2429,23 +2268,17 @@ idmap_getwinnamebygid(gid_t gid, int flag, char **name, char **domain) } idmap_stat -idmap_flush(idmap_handle_t *handle, idmap_flush_op op) +idmap_flush(idmap_flush_op op) { - CLIENT *clnt; - enum clnt_stat clntstat; - idmap_retcode res; + idmap_retcode rc1, rc2; - res = IDMAP_SUCCESS; - _IDMAP_GET_CLIENT_HANDLE(handle, clnt); - - clntstat = clnt_call(clnt, IDMAP_FLUSH, + rc1 = _idmap_clnt_call(IDMAP_FLUSH, (xdrproc_t)xdr_idmap_flush_op, (caddr_t)&op, - (xdrproc_t)xdr_idmap_retcode, (caddr_t)&res, TIMEOUT); + (xdrproc_t)xdr_idmap_retcode, (caddr_t)&rc2, TIMEOUT); - if (clntstat != RPC_SUCCESS) { - return (_idmap_rpc2stat(clnt)); - } - return (res); + if (rc1 != IDMAP_SUCCESS) + return (rc1); + return (rc2); } diff --git a/usr/src/lib/libidmap/common/idmap_impl.h b/usr/src/lib/libidmap/common/idmap_impl.h index 0c4aba0abb..8dd4a7efb2 100644 --- a/usr/src/lib/libidmap/common/idmap_impl.h +++ b/usr/src/lib/libidmap/common/idmap_impl.h @@ -43,25 +43,7 @@ extern "C" { #endif -#define _IDMAP_HANDLE_RPC_DOORS 1 - -#define _IDMAP_GET_CLIENT_HANDLE(h, clnt) \ - if (h == NULL) \ - return (IDMAP_ERR_CLIENT_HANDLE);\ - if (h->type != _IDMAP_HANDLE_RPC_DOORS) \ - return (IDMAP_ERR_NOTSUPPORTED);\ - clnt = (CLIENT *)h->privhandle;\ - if (clnt == NULL)\ - return (IDMAP_ERR_RPC_HANDLE); - -struct idmap_handle { - int type; - void *privhandle; - /* locks */ -}; - struct idmap_udt_handle { - struct idmap_handle *ih; idmap_update_batch batch; uint64_t next; int64_t error_index; @@ -90,7 +72,6 @@ typedef struct idmap_get_res { } idmap_get_res_t; struct idmap_get_handle { - struct idmap_handle *ih; idmap_mapping_batch batch; idmap_get_res_t *retlist; uint64_t next; @@ -104,7 +85,6 @@ struct idmap_get_handle { gh->next = 0; struct idmap_iter { - struct idmap_handle *ih; int type; uint64_t limit; void *arg; @@ -122,11 +102,15 @@ typedef struct stat_table { typedef idmap_retcode _idmap_stat; +extern idmap_stat _idmap_clnt_call(const rpcproc_t, + const xdrproc_t, const caddr_t, + const xdrproc_t, caddr_t out, + const struct timeval); + extern idmap_retcode _udt_extend_batch(idmap_udt_handle_t *); extern idmap_retcode _get_ids_extend_batch(idmap_get_handle_t *); extern idmap_stat _iter_get_next_list(int, idmap_iter_t *, void *, uchar_t **, size_t, xdrproc_t, xdrproc_t); -extern idmap_stat _idmap_rpc2stat(CLIENT *); extern idmap_logger_t logger; diff --git a/usr/src/lib/libidmap/common/idmap_priv.h b/usr/src/lib/libidmap/common/idmap_priv.h index 30547b881d..2b28b219be 100644 --- a/usr/src/lib/libidmap/common/idmap_priv.h +++ b/usr/src/lib/libidmap/common/idmap_priv.h @@ -68,8 +68,7 @@ typedef struct idmap_iter idmap_iter_t; */ /* Create handle for updates */ -extern idmap_stat idmap_udt_create(idmap_handle_t *, - idmap_udt_handle_t **); +extern idmap_stat idmap_udt_create(idmap_udt_handle_t **); /* Commit */ extern idmap_stat idmap_udt_commit(idmap_udt_handle_t *); @@ -100,15 +99,14 @@ extern idmap_stat idmap_udt_rm_namerule(idmap_udt_handle_t *, boolean_t, extern idmap_stat idmap_udt_flush_namerules(idmap_udt_handle_t *); /* Flush caches */ -extern idmap_stat idmap_flush(idmap_handle_t *, idmap_flush_op); +extern idmap_stat idmap_flush(idmap_flush_op); /* * Iterator API */ /* Create a iterator to get SID to UID/GID mappings */ -extern idmap_stat idmap_iter_mappings(idmap_handle_t *, idmap_iter_t **, - int flag); +extern idmap_stat idmap_iter_mappings(idmap_iter_t **, int flag); /* Iterate through the SID to UID/GID mappings */ extern idmap_stat idmap_iter_next_mapping(idmap_iter_t *, char **, @@ -116,7 +114,7 @@ extern idmap_stat idmap_iter_next_mapping(idmap_iter_t *, char **, boolean_t *, int *, idmap_info *); /* Create a iterator to get name-based mapping rules */ -extern idmap_stat idmap_iter_namerules(idmap_handle_t *, const char *, +extern idmap_stat idmap_iter_namerules(const char *, boolean_t, boolean_t, const char *, const char *, idmap_iter_t **); /* Iterate through the name-based mapping rules */ @@ -133,11 +131,11 @@ extern void idmap_iter_destroy(idmap_iter_t *); /* * Get mapping */ -extern idmap_stat idmap_get_w2u_mapping(idmap_handle_t *, const char *, +extern idmap_stat idmap_get_w2u_mapping(const char *, idmap_rid_t *, const char *, const char *, int, int *, int *, uid_t *, char **, int *, idmap_info *); -extern idmap_stat idmap_get_u2w_mapping(idmap_handle_t *, uid_t *, +extern idmap_stat idmap_get_u2w_mapping(uid_t *, const char *, int, int, int *, char **, idmap_rid_t *, char **, char **, int *, idmap_info *); @@ -188,10 +186,8 @@ extern idmap_stat idmap_getext_sidbygid(idmap_get_handle_t *, gid_t, int, char **, idmap_rid_t *, idmap_info *, idmap_stat *); /* Properties */ -extern idmap_stat idmap_get_prop_ds(idmap_handle_t *, idmap_prop_type, - idmap_ad_disc_ds_t *); -extern idmap_stat idmap_get_prop_str(idmap_handle_t *, idmap_prop_type, - char **); +extern idmap_stat idmap_get_prop_ds(idmap_prop_type, idmap_ad_disc_ds_t *); +extern idmap_stat idmap_get_prop_str(idmap_prop_type, char **); /* * Trace diff --git a/usr/src/lib/libidmap/common/mapfile-vers b/usr/src/lib/libidmap/common/mapfile-vers index cee7740d55..7a57d184c9 100644 --- a/usr/src/lib/libidmap/common/mapfile-vers +++ b/usr/src/lib/libidmap/common/mapfile-vers @@ -60,7 +60,6 @@ SYMBOL_VERSION SUNWprivate { directory_sid_from_group_name; directory_sid_from_name; directory_sid_from_user_name; - idmap_fini; idmap_flush; idmap_free; idmap_get_create; @@ -87,7 +86,6 @@ SYMBOL_VERSION SUNWprivate { idmap_how_clear; idmap_info_free; idmap_info_mov; - idmap_init; idmap_iter_destroy; idmap_iter_mappings; idmap_iter_namerules; diff --git a/usr/src/lib/libidmap/common/utils.c b/usr/src/lib/libidmap/common/utils.c index 1c073b75d6..1068e0aa2c 100644 --- a/usr/src/lib/libidmap/common/utils.c +++ b/usr/src/lib/libidmap/common/utils.c @@ -19,12 +19,9 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. */ -#pragma ident "%Z%%M% %I% %E% SMI" - /* * Utility routines */ @@ -33,6 +30,9 @@ #include #include #include +#include +#include +#include #include "idmap_impl.h" #define _UDT_SIZE_INCR 1 @@ -41,6 +41,21 @@ static struct timeval TIMEOUT = { 25, 0 }; +struct idmap_handle { + CLIENT *client; + boolean_t failed; + rwlock_t lock; +}; + +static struct idmap_handle idmap_handle = { + NULL, /* client */ + B_TRUE, /* failed */ + DEFAULTRWLOCK, /* lock */ +}; + +static idmap_stat _idmap_clnt_connect(void); +static void _idmap_clnt_disconnect(void); + idmap_retcode _udt_extend_batch(idmap_udt_handle_t *udthandle) { @@ -103,13 +118,10 @@ _iter_get_next_list(int type, idmap_iter_t *iter, void *arg, uchar_t **list, size_t valsize, xdrproc_t xdr_arg_proc, xdrproc_t xdr_res_proc) { - - CLIENT *clnt; - enum clnt_stat clntstat; + idmap_stat rc; iter->next = 0; iter->retlist = NULL; - _IDMAP_GET_CLIENT_HANDLE(iter->ih, clnt); /* init the result */ if (*list) { @@ -122,20 +134,25 @@ _iter_get_next_list(int type, idmap_iter_t *iter, } (void) memset(*list, 0, valsize); - clntstat = clnt_call(clnt, type, + rc = _idmap_clnt_call(type, xdr_arg_proc, (caddr_t)arg, xdr_res_proc, (caddr_t)*list, TIMEOUT); - if (clntstat != RPC_SUCCESS) { + if (rc != IDMAP_SUCCESS) { free(*list); - return (_idmap_rpc2stat(clnt)); + return (rc); } iter->retlist = *list; return (IDMAP_SUCCESS); } +/* + * Convert the return values from an RPC request into an idmap return code. + * Set errno on error. + */ +static idmap_stat -_idmap_rpc2stat(CLIENT *clnt) +_idmap_rpc2stat(enum clnt_stat clntstat, CLIENT *clnt) { /* * We only deal with door_call(3C) errors here. We look at @@ -144,19 +161,191 @@ _idmap_rpc2stat(CLIENT *clnt) * and others. */ struct rpc_err r_err; - if (clnt) { - clnt_geterr(clnt, &r_err); - errno = r_err.re_errno; - switch (r_err.re_errno) { - case ENOMEM: - return (IDMAP_ERR_MEMORY); - case EBADF: - return (IDMAP_ERR_RPC_HANDLE); - default: - return (IDMAP_ERR_RPC); + + if (clntstat == RPC_SUCCESS) + return (IDMAP_SUCCESS); + + clnt_geterr(clnt, &r_err); + errno = r_err.re_errno; + switch (r_err.re_errno) { + case ENOMEM: + return (IDMAP_ERR_MEMORY); + case EBADF: + return (IDMAP_ERR_RPC_HANDLE); + default: + return (IDMAP_ERR_RPC); + } +} + +/* + * Management of the connection to idmapd. + * + * The intent is that connections to idmapd are automatically maintained, + * reconnecting if necessary. No attempt is made to retry connnection + * attempts; a failure to connect yields an immediate error return. + * + * State of the connection is maintained through the "client" and "failed" + * elements of the handle structure: + * + * client failed + * NULL true Failed on a previous request and was not recovered. + * NULL false Should never happen. + * nonNULL true Structure exists, but an error has occurred. Waiting + * for a chance to attempt to reconnect. + * nonNULL false Connection is good. + * + * Note that the initial state is NULL/true, so that the first request + * will establish the initial connection. + * + * Concurrency is managed through the rw lock "lock". Only the writer is + * allowed to connect or disconnect, and thus only the writer can set + * "failed" to "false". Readers are allowed to use the "client" pointer, + * and to set "failed" to "true", indicating that they have encountered a + * failure. The "client" pointer is only valid while one holds a reader + * lock. Once "failed" has been set to "true", all requests (including + * the retry of the failing request) will attempt to gain the writer lock. + * When they succeed, indicating that there are no requests in flight and + * thus no outstanding references to the CLIENT structure, they check + * again to see if the connection is still failed (since another thread + * might have fixed it), and then if it is still failed they disconnect + * and reconnect. + */ + +/* + * Make an RPC call. Automatically reconnect if the connection to idmapd + * fails. Convert RPC results to idmap return codes. + */ +idmap_stat +_idmap_clnt_call( + const rpcproc_t procnum, + const xdrproc_t inproc, + const caddr_t in, + const xdrproc_t outproc, + caddr_t out, + const struct timeval tout) +{ + enum clnt_stat clntstat; + idmap_stat rc; + + (void) rw_rdlock(&idmap_handle.lock); + for (;;) { + if (idmap_handle.failed) { + /* No connection. Bid to see if we should fix it. */ + (void) rw_unlock(&idmap_handle.lock); + /* Somebody else might fix it here. */ + (void) rw_wrlock(&idmap_handle.lock); + /* + * At this point, everybody else is asleep waiting + * for us. Check to see if somebody else has already + * fixed the problem. + */ + if (idmap_handle.failed) { + /* It's our job to fix. */ + _idmap_clnt_disconnect(); + rc = _idmap_clnt_connect(); + if (rc != IDMAP_SUCCESS) { + /* We couldn't fix it. */ + assert(idmap_handle.failed); + assert(idmap_handle.client == NULL); + break; + } + /* We fixed it. */ + idmap_handle.failed = B_FALSE; + } + + /* It's fixed now. */ + (void) rw_unlock(&idmap_handle.lock); + /* + * Starting here, somebody might declare it failed + * again. + */ + (void) rw_rdlock(&idmap_handle.lock); + continue; + } + + clntstat = clnt_call(idmap_handle.client, procnum, inproc, in, + outproc, out, tout); + rc = _idmap_rpc2stat(clntstat, idmap_handle.client); + if (rc == IDMAP_ERR_RPC_HANDLE) { + /* Failed. Needs to be reconnected. */ + idmap_handle.failed = B_TRUE; + continue; + } + + /* Success or unrecoverable failure. */ + break; + } + (void) rw_unlock(&idmap_handle.lock); + return (rc); +} + +#define MIN_STACK_NEEDS 65536 + +/* + * Connect to idmapd. + * Must be single-threaded through rw_wrlock(&idmap_handle.lock). + */ +static +idmap_stat +_idmap_clnt_connect(void) +{ + uint_t sendsz = 0; + stack_t st; + + /* + * clnt_door_call() alloca()s sendsz bytes (twice too, once for + * the call args buffer and once for the call result buffer), so + * we want to pick a sendsz that will be large enough, but not + * too large. + */ + if (stack_getbounds(&st) == 0) { + /* + * Estimate how much stack space is left; + * st.ss_sp is the top of stack. + */ + if ((char *)&sendsz < (char *)st.ss_sp) + /* stack grows up */ + sendsz = ((char *)st.ss_sp - (char *)&sendsz); + else + /* stack grows down */ + sendsz = ((char *)&sendsz - (char *)st.ss_sp); + + if (sendsz <= MIN_STACK_NEEDS) { + sendsz = 0; /* RPC call may fail */ + } else { + /* Leave 64Kb (just a guess) for our needs */ + sendsz -= MIN_STACK_NEEDS; + + /* Divide the stack space left by two */ + sendsz = RNDUP(sendsz / 2); + + /* Limit sendsz to 256KB */ + if (sendsz > IDMAP_MAX_DOOR_RPC) + sendsz = IDMAP_MAX_DOOR_RPC; } } - /* null handle */ - return (IDMAP_ERR_RPC_HANDLE); + idmap_handle.client = clnt_door_create(IDMAP_PROG, IDMAP_V1, sendsz); + if (idmap_handle.client == NULL) + return (IDMAP_ERR_RPC); + + return (IDMAP_SUCCESS); +} + +/* + * Disconnect from idmapd, if we're connected. + */ +static +void +_idmap_clnt_disconnect(void) +{ + CLIENT *clnt; + + clnt = idmap_handle.client; + if (clnt != NULL) { + if (clnt->cl_auth) + auth_destroy(clnt->cl_auth); + clnt_destroy(clnt); + idmap_handle.client = NULL; + } } diff --git a/usr/src/lib/libsec/common/acltext.c b/usr/src/lib/libsec/common/acltext.c index 952ea28c64..f270503433 100644 --- a/usr/src/lib/libsec/common/acltext.c +++ b/usr/src/lib/libsec/common/acltext.c @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 1993, 2010, Oracle and/or its affiliates. All rights reserved. */ /*LINTLIBRARY*/ @@ -120,7 +119,6 @@ prgname(gid_t gid, char *gidp, size_t buflen, int noresolve) static int getsidname(uid_t who, boolean_t user, char **sidp, boolean_t noresolve) { - idmap_handle_t *idmap_hdl = NULL; idmap_get_handle_t *get_hdl = NULL; idmap_stat status; idmap_rid_t rid; @@ -144,8 +142,7 @@ getsidname(uid_t who, boolean_t user, char **sidp, boolean_t noresolve) IDMAP_REQ_FLG_USE_CACHE, &name, &domain); } if (error != IDMAP_SUCCESS) { - if (idmap_init(&idmap_hdl) == IDMAP_SUCCESS && - idmap_get_create(idmap_hdl, &get_hdl) == IDMAP_SUCCESS) { + if (idmap_get_create(&get_hdl) == IDMAP_SUCCESS) { if (user) error = idmap_get_sidbyuid(get_hdl, who, IDMAP_REQ_FLG_USE_CACHE, &domain, &rid, @@ -168,8 +165,6 @@ getsidname(uid_t who, boolean_t user, char **sidp, boolean_t noresolve) } if (get_hdl) idmap_get_destroy(get_hdl); - if (idmap_hdl) - (void) idmap_fini(idmap_hdl); } else { int len; diff --git a/usr/src/lib/libsec/common/aclutils.c b/usr/src/lib/libsec/common/aclutils.c index afe36a3aaa..ba7117c7f7 100644 --- a/usr/src/lib/libsec/common/aclutils.c +++ b/usr/src/lib/libsec/common/aclutils.c @@ -740,7 +740,6 @@ acl_error(const char *fmt, ...) int sid_to_id(char *sid, boolean_t user, uid_t *id) { - idmap_handle_t *idmap_hdl = NULL; idmap_get_handle_t *get_hdl = NULL; char *rid_start = NULL; idmap_stat status; @@ -757,8 +756,7 @@ sid_to_id(char *sid, boolean_t user, uid_t *id) errno = 0; rid = strtoul(rid_start--, &end, 10); if (errno == 0 && *end == '\0') { - if (idmap_init(&idmap_hdl) == IDMAP_SUCCESS && - idmap_get_create(idmap_hdl, &get_hdl) == + if (idmap_get_create(&get_hdl) == IDMAP_SUCCESS) { if (user) error = idmap_get_uidbysid(get_hdl, @@ -781,8 +779,6 @@ sid_to_id(char *sid, boolean_t user, uid_t *id) } if (get_hdl) idmap_get_destroy(get_hdl); - if (idmap_hdl) - (void) idmap_fini(idmap_hdl); } else { error = 1; } diff --git a/usr/src/lib/libzfs/common/libzfs_dataset.c b/usr/src/lib/libzfs/common/libzfs_dataset.c index b23c45f354..bb3dd9e7da 100644 --- a/usr/src/lib/libzfs/common/libzfs_dataset.c +++ b/usr/src/lib/libzfs/common/libzfs_dataset.c @@ -2201,14 +2201,11 @@ static int idmap_id_to_numeric_domain_rid(uid_t id, boolean_t isuser, char **domainp, idmap_rid_t *ridp) { - idmap_handle_t *idmap_hdl = NULL; idmap_get_handle_t *get_hdl = NULL; idmap_stat status; int err = EINVAL; - if (idmap_init(&idmap_hdl) != IDMAP_SUCCESS) - goto out; - if (idmap_get_create(idmap_hdl, &get_hdl) != IDMAP_SUCCESS) + if (idmap_get_create(&get_hdl) != IDMAP_SUCCESS) goto out; if (isuser) { @@ -2227,8 +2224,6 @@ idmap_id_to_numeric_domain_rid(uid_t id, boolean_t isuser, out: if (get_hdl) idmap_get_destroy(get_hdl); - if (idmap_hdl) - (void) idmap_fini(idmap_hdl); return (err); } diff --git a/usr/src/lib/nsswitch/ad/common/ad_common.h b/usr/src/lib/nsswitch/ad/common/ad_common.h index a328b00b9a..7592d3613b 100644 --- a/usr/src/lib/nsswitch/ad/common/ad_common.h +++ b/usr/src/lib/nsswitch/ad/common/ad_common.h @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. */ #ifndef _AD_COMMON_H @@ -82,7 +81,6 @@ struct ad_backend { fnf adobj2str; char *buffer; int buflen; - idmap_handle_t *ih; uid_t uid; adutils_result_t *result; nss_ad_db_type_t db_type; diff --git a/usr/src/lib/nsswitch/ad/common/getgrent.c b/usr/src/lib/nsswitch/ad/common/getgrent.c index b5f70666ba..84481bb09f 100644 --- a/usr/src/lib/nsswitch/ad/common/getgrent.c +++ b/usr/src/lib/nsswitch/ad/common/getgrent.c @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. */ #include @@ -72,7 +71,6 @@ getbynam(ad_backend_ptr be, void *a) idmap_stat idmaprc; gid_t gid; int is_user, is_wuser; - idmap_handle_t *ih; be->db_type = NSS_AD_DB_GROUP_BYNAME; @@ -89,14 +87,10 @@ getbynam(ad_backend_ptr be, void *a) /* * Map the name to gid using idmap service. */ - idmaprc = idmap_init(&ih); - if (idmaprc != IDMAP_SUCCESS) - return ((nss_status_t)NSS_NOTFOUND); is_wuser = -1; is_user = 0; /* Map name to gid */ - idmaprc = idmap_get_w2u_mapping(ih, NULL, NULL, name, dname, + idmaprc = idmap_get_w2u_mapping(NULL, NULL, name, dname, 0, &is_user, &is_wuser, &gid, NULL, NULL, NULL); - (void) idmap_fini(ih); if (idmaprc != IDMAP_SUCCESS) { RESET_ERRNO(); return ((nss_status_t)NSS_NOTFOUND); @@ -134,9 +128,7 @@ getbygid(ad_backend_ptr be, void *a) goto out; /* Map the given GID to a SID using the idmap service */ - if (idmap_init(&be->ih) != 0) - goto out; - if (idmap_get_u2w_mapping(be->ih, &argp->key.gid, NULL, 0, + if (idmap_get_u2w_mapping(&argp->key.gid, NULL, 0, 0, NULL, NULL, NULL, &winname, &windomain, NULL, NULL) != 0) { RESET_ERRNO(); @@ -161,8 +153,6 @@ getbygid(ad_backend_ptr be, void *a) out: idmap_free(winname); idmap_free(windomain); - (void) idmap_fini(be->ih); - be->ih = NULL; return (stat); } diff --git a/usr/src/lib/nsswitch/ad/common/getpwnam.c b/usr/src/lib/nsswitch/ad/common/getpwnam.c index ece50a54b0..ff2140b59b 100644 --- a/usr/src/lib/nsswitch/ad/common/getpwnam.c +++ b/usr/src/lib/nsswitch/ad/common/getpwnam.c @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. */ #include @@ -192,9 +191,7 @@ _nss_ad_passwd2str(ad_backend_ptr be, nss_XbyY_args_t *argp) nss_result = NSS_STR_PARSE_PARSE; /* Create handles for idmap service */ - if (be->ih == NULL && idmap_init(&be->ih) != 0) - goto result_pwd2str; - if (idmap_get_create(be->ih, &ig) != 0) + if (idmap_get_create(&ig) != 0) goto result_pwd2str; /* Get name */ @@ -278,8 +275,6 @@ _nss_ad_passwd2str(ad_backend_ptr be, nss_XbyY_args_t *argp) result_pwd2str: idmap_get_destroy(ig); - (void) idmap_fini(be->ih); - be->ih = NULL; (void) adutils_freeresult(&be->result); free(domain); if (homedir != NULL_STR && homedir_v != NULL && @@ -310,7 +305,6 @@ getbyname(ad_backend_ptr be, void *a) uid_t uid; gid_t gid; int is_user, is_wuser, try_idmap; - idmap_handle_t *ih; be->db_type = NSS_AD_DB_PASSWD_BYNAME; @@ -329,17 +323,13 @@ getbyname(ad_backend_ptr be, void *a) * call fails then this will save us doing AD discovery and * AD lookup here. */ - if (idmap_init(&be->ih) != IDMAP_SUCCESS) - return ((nss_status_t)NSS_NOTFOUND); flag = (strcasecmp(dname, WK_DOMAIN) == 0) ? IDMAP_REQ_FLG_WK_OR_LOCAL_SIDS_ONLY : 0; is_wuser = -1; is_user = 1; - if (idmap_get_w2u_mapping(be->ih, NULL, NULL, name, + if (idmap_get_w2u_mapping(NULL, NULL, name, dname, flag, &is_user, &is_wuser, &be->uid, NULL, NULL, NULL) != IDMAP_SUCCESS) { - (void) idmap_fini(be->ih); - be->ih = NULL; RESET_ERRNO(); return ((nss_status_t)NSS_NOTFOUND); } @@ -357,11 +347,8 @@ getbyname(ad_backend_ptr be, void *a) dname, &try_idmap); free(searchfilter); - if (!try_idmap) { - (void) idmap_fini(be->ih); - be->ih = NULL; + if (!try_idmap) return (stat); - } } @@ -372,10 +359,8 @@ getbyname(ad_backend_ptr be, void *a) */ is_wuser = -1; is_user = 0; /* Map name to primary gid */ - idmaprc = idmap_get_w2u_mapping(be->ih, NULL, NULL, name, dname, + idmaprc = idmap_get_w2u_mapping(NULL, NULL, name, dname, flag, &is_user, &is_wuser, &gid, NULL, NULL, NULL); - (void) idmap_fini(be->ih); - be->ih = NULL; if (idmaprc != IDMAP_SUCCESS) { RESET_ERRNO(); return ((nss_status_t)NSS_NOTFOUND); @@ -424,9 +409,7 @@ getbyuid(ad_backend_ptr be, void *a) goto out; /* Map the given UID to a SID using the idmap service */ - if (idmap_init(&be->ih) != 0) - goto out; - if (idmap_get_u2w_mapping(be->ih, &argp->key.uid, NULL, 0, + if (idmap_get_u2w_mapping(&argp->key.uid, NULL, 0, 1, NULL, &sidprefix, &rid, &winname, &windomain, NULL, NULL) != 0) { RESET_ERRNO(); @@ -461,13 +444,10 @@ getbyuid(ad_backend_ptr be, void *a) /* Map winname to primary gid using idmap service */ is_user = 0; is_wuser = -1; - idmaprc = idmap_get_w2u_mapping(be->ih, NULL, NULL, + idmaprc = idmap_get_w2u_mapping(NULL, NULL, winname, windomain, 0, &is_user, &is_wuser, &gid, NULL, NULL, NULL); - (void) idmap_fini(be->ih); - be->ih = NULL; - if (idmaprc != IDMAP_SUCCESS) { RESET_ERRNO(); goto out; @@ -486,8 +466,6 @@ out: idmap_free(sidprefix); idmap_free(winname); idmap_free(windomain); - (void) idmap_fini(be->ih); - be->ih = NULL; return (stat); } diff --git a/usr/src/lib/nsswitch/ad/common/getspent.c b/usr/src/lib/nsswitch/ad/common/getspent.c index 257540c8db..a66d8b122b 100644 --- a/usr/src/lib/nsswitch/ad/common/getspent.c +++ b/usr/src/lib/nsswitch/ad/common/getspent.c @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. */ #include @@ -80,7 +79,6 @@ getbynam(ad_backend_ptr be, void *a) idmap_stat idmaprc; uid_t uid; int is_user, is_wuser; - idmap_handle_t *ih; be->db_type = NSS_AD_DB_SHADOW_BYNAME; @@ -98,14 +96,10 @@ getbynam(ad_backend_ptr be, void *a) * Use idmap service to verify that the given * name is a valid Windows name. */ - idmaprc = idmap_init(&ih); - if (idmaprc != IDMAP_SUCCESS) - return ((nss_status_t)NSS_NOTFOUND); is_wuser = -1; is_user = 1; - idmaprc = idmap_get_w2u_mapping(ih, NULL, NULL, name, dname, + idmaprc = idmap_get_w2u_mapping(NULL, NULL, name, dname, 0, &is_user, &is_wuser, &uid, NULL, NULL, NULL); - (void) idmap_fini(ih); if (idmaprc != IDMAP_SUCCESS) { RESET_ERRNO(); return ((nss_status_t)NSS_NOTFOUND); diff --git a/usr/src/lib/smbsrv/libmlsvc/common/dssetup_clnt.c b/usr/src/lib/smbsrv/libmlsvc/common/dssetup_clnt.c index 9c36e26f91..95f96d0a97 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/dssetup_clnt.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/dssetup_clnt.c @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. */ /* @@ -78,3 +77,20 @@ dssetup_get_domain_info(ds_primary_domain_info_t *ds_info) ndr_rpc_unbind(&handle); return (0); } + +int +dssetup_check_service(void) +{ + ds_primary_domain_info_t ds_info; + int rc; + + bzero(&ds_info, sizeof (ds_primary_domain_info_t)); + + if ((rc = dssetup_get_domain_info(&ds_info)) == 0) { + free(ds_info.nt_domain); + free(ds_info.dns_domain); + free(ds_info.forest); + } + + return (rc); +} diff --git a/usr/src/lib/smbsrv/libmlsvc/common/libmlsvc.h b/usr/src/lib/smbsrv/libmlsvc/common/libmlsvc.h index 267c78fe12..03603a61aa 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/libmlsvc.h +++ b/usr/src/lib/smbsrv/libmlsvc/common/libmlsvc.h @@ -60,11 +60,11 @@ uint32_t lsa_lookup_sid(smb_sid_t *, smb_account_t *); extern boolean_t smb_locate_dc(char *, char *, smb_domainex_t *); +extern int dssetup_check_service(void); extern void dssetup_clear_domain_info(void); extern void mlsvc_disconnect(const char *); extern int mlsvc_init(void); extern void mlsvc_fini(void); -extern int mlsvc_ping(const char *); extern DWORD mlsvc_netlogon(char *, char *); extern DWORD mlsvc_join(smb_domainex_t *, char *, char *); diff --git a/usr/src/lib/smbsrv/libmlsvc/common/mapfile-vers b/usr/src/lib/smbsrv/libmlsvc/common/mapfile-vers index c3af6a8f20..bb9cd09573 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/mapfile-vers +++ b/usr/src/lib/smbsrv/libmlsvc/common/mapfile-vers @@ -42,6 +42,7 @@ SYMBOL_VERSION SUNWprivate { global: dfs_get_referrals; dfs_info_free; + dssetup_check_service; dssetup_clear_domain_info; lsa_lookup_name; lsa_lookup_sid; diff --git a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_util.c b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_util.c index be1dcb8a52..f835934e5e 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_util.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_util.c @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. */ /* @@ -142,12 +141,6 @@ mlsvc_join(smb_domainex_t *dxi, char *user, char *plain_text) return (status); } -int -mlsvc_ping(const char *server) -{ - return (smbrdr_echo(server)); -} - void mlsvc_disconnect(const char *server) { diff --git a/usr/src/lib/smbsrv/libmlsvc/common/netr_logon.c b/usr/src/lib/smbsrv/libmlsvc/common/netr_logon.c index 46e7117f92..1e346ab41e 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/netr_logon.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/netr_logon.c @@ -151,18 +151,11 @@ netlogon_logon(smb_logon_t *user_info, smb_token_t *token) mlsvc_handle_t netr_handle; smb_domainex_t di; uint32_t status; - int retries = 0, server_changed = 0; + int retries = 0; (void) smb_getdomainname(resource_domain, SMB_PI_MAX_DOMAIN); - if (!smb_domain_getinfo(&di)) - return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO); - - if (mlsvc_ping(di.d_dc) < 0) { - /* - * We had a session to the DC but it's not responding. - * So drop the credential chain. - */ + if (!smb_domain_getinfo(&di)) { netr_invalidate_chain(); return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO); } @@ -175,12 +168,12 @@ netlogon_logon(smb_logon_t *user_info, smb_token_t *token) if (di.d_dc && (*netr_global_info.server != '\0')) { (void) snprintf(server, sizeof (server), "\\\\%s", di.d_dc); - server_changed = strncasecmp(netr_global_info.server, - server, strlen(server)); + if (strncasecmp(netr_global_info.server, + server, strlen(server)) != 0) + netr_invalidate_chain(); } - if (server_changed || - (netr_global_info.flags & NETR_FLG_VALID) == 0 || + if ((netr_global_info.flags & NETR_FLG_VALID) == 0 || !smb_match_netlogon_seqnum()) { status = netlogon_auth(di.d_dc, &netr_handle, NETR_FLG_NULL); diff --git a/usr/src/lib/smbsrv/libmlsvc/common/smb_logon.c b/usr/src/lib/smbsrv/libmlsvc/common/smb_logon.c index 850b8f5858..71b6f278d6 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/smb_logon.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/smb_logon.c @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. */ #include @@ -136,7 +135,7 @@ static int smb_token_sids2ids(smb_token_t *token) { idmap_stat stat; - int nmaps, retries = 0; + int nmaps; smb_idmap_batch_t sib; /* @@ -148,21 +147,19 @@ smb_token_sids2ids(smb_token_t *token) else nmaps = token->tkn_win_grps.i_cnt + 3; - do { - stat = smb_idmap_batch_create(&sib, nmaps, SMB_IDMAP_SID2ID); - if (stat != IDMAP_SUCCESS) - return (-1); - - stat = smb_token_idmap(token, &sib); - if (stat != IDMAP_SUCCESS) { - smb_idmap_batch_destroy(&sib); - return (-1); - } + stat = smb_idmap_batch_create(&sib, nmaps, SMB_IDMAP_SID2ID); + if (stat != IDMAP_SUCCESS) + return (-1); - stat = smb_idmap_batch_getmappings(&sib); + stat = smb_token_idmap(token, &sib); + if (stat != IDMAP_SUCCESS) { smb_idmap_batch_destroy(&sib); - smb_idmap_check("smb_idmap_batch_getmappings", stat); - } while (stat == IDMAP_ERR_RPC_HANDLE && retries++ < 3); + return (-1); + } + + stat = smb_idmap_batch_getmappings(&sib); + smb_idmap_batch_destroy(&sib); + smb_idmap_check("smb_idmap_batch_getmappings", stat); return (stat == IDMAP_SUCCESS ? 0 : -1); } diff --git a/usr/src/lib/smbsrv/libmlsvc/common/spoolss_svc.c b/usr/src/lib/smbsrv/libmlsvc/common/spoolss_svc.c index b2897c48cc..8630e5d10c 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/spoolss_svc.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/spoolss_svc.c @@ -168,11 +168,17 @@ static ndr_service_t spoolss_service = { spoolss_stub_table /* stub_table */ }; +/* + * Defer calling spoolss_cups_init() until something actually + * needs access to CUPS due to the libcups dependency on OpenSSL. + * OpenSSL is not MT-safe and initializing CUPS here can crash + * OpenSSL if it collides with other threads that are in other + * libraries that are attempting to use OpenSSL. + */ void spoolss_initialize(void) { (void) ndr_svc_register(&spoolss_service); - (void) spoolss_cups_init(); } void diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_idmap.c b/usr/src/lib/smbsrv/libsmb/common/smb_idmap.c index deee29188d..8201db46aa 100644 --- a/usr/src/lib/smbsrv/libsmb/common/smb_idmap.c +++ b/usr/src/lib/smbsrv/libsmb/common/smb_idmap.c @@ -19,37 +19,17 @@ * CDDL HEADER END */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. */ #include #include -#include #include -static idmap_handle_t *smb_idmap_hd; -static mutex_t smb_idmap_mutex; - static int smb_idmap_batch_binsid(smb_idmap_batch_t *sib); -static void -smb_idmap_reset(void) -{ - (void) mutex_lock(&smb_idmap_mutex); - - if (smb_idmap_hd != NULL) { - (void) idmap_fini(smb_idmap_hd); - smb_idmap_hd = NULL; - } - - (void) mutex_unlock(&smb_idmap_mutex); -} - /* - * Report an idmap error. If the error appears to be connection - * related, use fini to reset. A new handle will be generated on - * the next open. + * Report an idmap error. */ void smb_idmap_check(const char *s, idmap_stat stat) @@ -58,44 +38,8 @@ smb_idmap_check(const char *s, idmap_stat stat) if (s == NULL) s = "smb_idmap_check"; - syslog(LOG_ERR, "%s: %s", s, idmap_stat2string(NULL, stat)); - - switch (stat) { - case IDMAP_ERR_RPC_HANDLE: - case IDMAP_ERR_RPC: - case IDMAP_ERR_CLIENT_HANDLE: - smb_idmap_reset(); - break; - default: - break; - } - } -} - -static idmap_handle_t * -smb_idmap_enter(void) -{ - idmap_stat stat; - - (void) mutex_lock(&smb_idmap_mutex); - - if (smb_idmap_hd == NULL) { - if ((stat = idmap_init(&smb_idmap_hd)) < 0) { - syslog(LOG_ERR, - "smb_idmap_enter: idmap_init failed: %s", - idmap_stat2string(NULL, stat)); - (void) mutex_unlock(&smb_idmap_mutex); - return (NULL); - } + syslog(LOG_ERR, "%s: %s", s, idmap_stat2string(stat)); } - - return (smb_idmap_hd); -} - -static void -smb_idmap_exit(void) -{ - (void) mutex_unlock(&smb_idmap_mutex); } /* @@ -180,18 +124,13 @@ smb_idmap_getid(smb_sid_t *sid, uid_t *id, int *id_type) idmap_stat smb_idmap_batch_create(smb_idmap_batch_t *sib, uint16_t nmap, int flags) { - idmap_handle_t *hd; idmap_stat stat; if (!sib) return (IDMAP_ERR_ARG); - if ((hd = smb_idmap_enter()) == NULL) - return (IDMAP_ERR_OTHER); - bzero(sib, sizeof (smb_idmap_batch_t)); - stat = idmap_get_create(hd, &sib->sib_idmaph); - smb_idmap_exit(); + stat = idmap_get_create(&sib->sib_idmaph); if (stat != IDMAP_SUCCESS) { smb_idmap_check("idmap_get_create", stat); @@ -380,10 +319,8 @@ smb_idmap_batch_getmappings(smb_idmap_batch_t *sib) smb_idmap_t *sim; int i; - (void) mutex_lock(&smb_idmap_mutex); if ((stat = idmap_get_mappings(sib->sib_idmaph)) != IDMAP_SUCCESS) { smb_idmap_check("idmap_get_mappings", stat); - (void) mutex_unlock(&smb_idmap_mutex); return (stat); } @@ -396,7 +333,6 @@ smb_idmap_batch_getmappings(smb_idmap_batch_t *sib) smb_tracef("[%d] %d (%d)", sim->sim_idtype, sim->sim_rid, sim->sim_stat); } - (void) mutex_unlock(&smb_idmap_mutex); return (sim->sim_stat); } } @@ -404,7 +340,6 @@ smb_idmap_batch_getmappings(smb_idmap_batch_t *sib) if (smb_idmap_batch_binsid(sib) != 0) stat = IDMAP_ERR_OTHER; - (void) mutex_unlock(&smb_idmap_mutex); return (stat); } diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_sd.c b/usr/src/lib/smbsrv/libsmb/common/smb_sd.c index 1f36038f53..231c0f6932 100644 --- a/usr/src/lib/smbsrv/libsmb/common/smb_sd.c +++ b/usr/src/lib/smbsrv/libsmb/common/smb_sd.c @@ -29,6 +29,7 @@ #include #include +#include #include #include #include @@ -156,11 +157,18 @@ smb_sd_read_acl(char *path, smb_fssd_t *fs_sd) ace_t *z_ace; fs_sd->sd_gid = fs_sd->sd_uid = 0; - if (acl_trivial(path) != 1) - return (NT_STATUS_INTERNAL_ERROR); - if (acl_get(path, ACL_NO_TRIVIAL, &z_acl) != 0) - return (NT_STATUS_INTERNAL_ERROR); + errno = 0; + if (acl_get(path, 0, &z_acl) != 0) { + switch (errno) { + case EACCES: + return (NT_STATUS_ACCESS_DENIED); + case ENOENT: + return (NT_STATUS_OBJECT_PATH_NOT_FOUND); + default: + return (NT_STATUS_INTERNAL_ERROR); + } + } if ((z_ace = (ace_t *)z_acl->acl_aclp) == NULL) return (NT_STATUS_INVALID_ACL); diff --git a/usr/src/uts/common/fs/smbsrv/smb_ofile.c b/usr/src/uts/common/fs/smbsrv/smb_ofile.c index 40c367395a..6855a795bd 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_ofile.c +++ b/usr/src/uts/common/fs/smbsrv/smb_ofile.c @@ -943,6 +943,7 @@ smb_ofile_delete(void *arg) SMB_OFILE_VALID(of); ASSERT(of->f_refcnt == 0); ASSERT(of->f_state == SMB_OFILE_STATE_CLOSED); + ASSERT(!SMB_OFILE_OPLOCK_GRANTED(of)); tree = of->f_tree; smb_llist_enter(&tree->t_ofile_list, RW_WRITER); diff --git a/usr/src/uts/common/fs/smbsrv/smb_oplock.c b/usr/src/uts/common/fs/smbsrv/smb_oplock.c index f1dd6ab58a..6172b1726f 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_oplock.c +++ b/usr/src/uts/common/fs/smbsrv/smb_oplock.c @@ -56,12 +56,12 @@ static void smb_oplock_wait(smb_node_t *); static void smb_oplock_wait_ack(smb_node_t *, uint32_t); static void smb_oplock_timedout(smb_node_t *); -static smb_oplock_grant_t *smb_oplock_create_grant(smb_ofile_t *, uint8_t); -void smb_oplock_delete_grant(smb_oplock_grant_t *); +static smb_oplock_grant_t *smb_oplock_set_grant(smb_ofile_t *, uint8_t); +void smb_oplock_clear_grant(smb_oplock_grant_t *); static int smb_oplock_insert_grant(smb_node_t *, smb_oplock_grant_t *); static void smb_oplock_remove_grant(smb_node_t *, smb_oplock_grant_t *); static smb_oplock_grant_t *smb_oplock_exclusive_grant(list_t *); -static smb_oplock_grant_t *smb_oplock_find_grant(list_t *, smb_ofile_t *); +static smb_oplock_grant_t *smb_oplock_get_grant(smb_oplock_t *, smb_ofile_t *); static smb_oplock_break_t *smb_oplock_create_break(smb_node_t *); static smb_oplock_break_t *smb_oplock_get_break(void); @@ -73,7 +73,6 @@ static void smb_oplock_break_thread(); /* levelII oplock break requests (smb_oplock_break_t) */ static boolean_t smb_oplock_initialized = B_FALSE; static kmem_cache_t *smb_oplock_break_cache = NULL; -static kmem_cache_t *smb_oplock_grant_cache = NULL; static smb_llist_t smb_oplock_breaks; static smb_thread_t smb_oplock_thread; @@ -95,9 +94,6 @@ smb_oplock_init(void) smb_oplock_break_cache = kmem_cache_create("smb_oplock_break_cache", sizeof (smb_oplock_break_t), 8, NULL, NULL, NULL, NULL, NULL, 0); - smb_oplock_grant_cache = kmem_cache_create("smb_oplock_grant_cache", - sizeof (smb_oplock_grant_t), 8, NULL, NULL, NULL, NULL, NULL, 0); - smb_llist_constructor(&smb_oplock_breaks, sizeof (smb_oplock_break_t), offsetof(smb_oplock_break_t, ob_lnd)); @@ -109,7 +105,6 @@ smb_oplock_init(void) smb_thread_destroy(&smb_oplock_thread); smb_llist_destructor(&smb_oplock_breaks); kmem_cache_destroy(smb_oplock_break_cache); - kmem_cache_destroy(smb_oplock_grant_cache); return (rc); } @@ -141,7 +136,6 @@ smb_oplock_fini(void) smb_llist_destructor(&smb_oplock_breaks); kmem_cache_destroy(smb_oplock_break_cache); - kmem_cache_destroy(smb_oplock_grant_cache); } /* @@ -259,9 +253,9 @@ smb_oplock_acquire(smb_request_t *sr, smb_node_t *node, smb_ofile_t *ofile) nbl_end_crit(node->vp); - og = smb_oplock_create_grant(ofile, op->op_oplock_level); + og = smb_oplock_set_grant(ofile, op->op_oplock_level); if (smb_oplock_insert_grant(node, og) != 0) { - smb_oplock_delete_grant(og); + smb_oplock_clear_grant(og); op->op_oplock_level = SMB_OPLOCK_NONE; mutex_exit(&ol->ol_mutex); return; @@ -471,7 +465,7 @@ smb_oplock_process_levelII_break(smb_node_t *node) smb_session_oplock_break(og->og_session, og->og_tid, og->og_fid, SMB_OPLOCK_BREAK_TO_NONE); smb_oplock_remove_grant(node, og); - smb_oplock_delete_grant(og); + smb_oplock_clear_grant(og); } mutex_exit(&ol->ol_mutex); @@ -527,7 +521,7 @@ smb_oplock_timedout(smb_node_t *node) case SMB_OPLOCK_BREAK_TO_NONE: og->og_level = SMB_OPLOCK_NONE; smb_oplock_remove_grant(node, og); - smb_oplock_delete_grant(og); + smb_oplock_clear_grant(og); break; case SMB_OPLOCK_BREAK_TO_LEVEL_II: og->og_level = SMB_OPLOCK_LEVEL_II; @@ -552,18 +546,15 @@ smb_oplock_release(smb_node_t *node, smb_ofile_t *of) { smb_oplock_t *ol; smb_oplock_grant_t *og; - list_t *grants; ol = &node->n_oplock; - grants = &ol->ol_grants; - mutex_enter(&ol->ol_mutex); smb_oplock_wait(node); - og = smb_oplock_find_grant(grants, of); + og = smb_oplock_get_grant(ol, of); if (og) { smb_oplock_remove_grant(node, og); - smb_oplock_delete_grant(og); + smb_oplock_clear_grant(og); if (ol->ol_break != SMB_OPLOCK_NO_BREAK) { ol->ol_break = SMB_OPLOCK_NO_BREAK; @@ -594,17 +585,14 @@ smb_oplock_ack(smb_node_t *node, smb_ofile_t *of, uint8_t brk) { smb_oplock_t *ol; smb_oplock_grant_t *og; - list_t *grants; boolean_t brk_to_none = B_FALSE; ol = &node->n_oplock; - grants = &ol->ol_grants; - mutex_enter(&ol->ol_mutex); smb_oplock_wait(node); if ((ol->ol_break == SMB_OPLOCK_NO_BREAK) || - ((og = smb_oplock_find_grant(grants, of)) == NULL)) { + ((og = smb_oplock_get_grant(ol, of)) == NULL)) { mutex_exit(&ol->ol_mutex); return; } @@ -628,7 +616,7 @@ smb_oplock_ack(smb_node_t *node, smb_ofile_t *of, uint8_t brk) if (og->og_level == SMB_OPLOCK_NONE) { smb_oplock_remove_grant(node, og); - smb_oplock_delete_grant(og); + smb_oplock_clear_grant(og); } ol->ol_break = SMB_OPLOCK_NO_BREAK; @@ -690,14 +678,15 @@ smb_oplock_wait(smb_node_t *node) } /* - * smb_oplock_create_grant + * smb_oplock_set_grant */ static smb_oplock_grant_t * -smb_oplock_create_grant(smb_ofile_t *of, uint8_t level) +smb_oplock_set_grant(smb_ofile_t *of, uint8_t level) { smb_oplock_grant_t *og; - og = kmem_cache_alloc(smb_oplock_grant_cache, KM_SLEEP); + og = &of->f_oplock_grant; + og->og_magic = SMB_OPLOCK_GRANT_MAGIC; og->og_level = level; og->og_ofile = of; @@ -709,12 +698,12 @@ smb_oplock_create_grant(smb_ofile_t *of, uint8_t level) } /* - * smb_oplock_delete_grant + * smb_oplock_clear_grant */ void -smb_oplock_delete_grant(smb_oplock_grant_t *og) +smb_oplock_clear_grant(smb_oplock_grant_t *og) { - kmem_cache_free(smb_oplock_grant_cache, og); + bzero(og, sizeof (smb_oplock_grant_t)); } /* @@ -782,23 +771,19 @@ smb_oplock_exclusive_grant(list_t *grants) } /* - * smb_oplock_find_grant + * smb_oplock_get_grant * * Find oplock grant corresponding to the specified ofile. */ static smb_oplock_grant_t * -smb_oplock_find_grant(list_t *grants, smb_ofile_t *ofile) +smb_oplock_get_grant(smb_oplock_t *ol, smb_ofile_t *ofile) { - smb_oplock_grant_t *og = NULL; + ASSERT(MUTEX_HELD(&ol->ol_mutex)); - for (og = list_head(grants); - og != NULL; - og = list_next(grants, og)) { - SMB_OPLOCK_GRANT_VALID(og); - if (og->og_ofile == ofile) - break; - } - return (og); + if (SMB_OFILE_OPLOCK_GRANTED(ofile)) + return (&ofile->f_oplock_grant); + else + return (NULL); } /* diff --git a/usr/src/uts/common/smbsrv/smb_ktypes.h b/usr/src/uts/common/smbsrv/smb_ktypes.h index 587135f4c7..c69226154d 100644 --- a/usr/src/uts/common/smbsrv/smb_ktypes.h +++ b/usr/src/uts/common/smbsrv/smb_ktypes.h @@ -572,6 +572,8 @@ typedef struct smb_oplock { #define SMB_OPLOCK_GRANT_MAGIC 0x4F4C4B47 /* OLKG */ #define SMB_OPLOCK_GRANT_VALID(p) \ ASSERT((p)->og_magic == SMB_OPLOCK_GRANT_MAGIC) +#define SMB_OFILE_OPLOCK_GRANTED(p) \ + ((p)->f_oplock_grant.og_magic == SMB_OPLOCK_GRANT_MAGIC) typedef struct smb_oplock_grant { uint32_t og_magic; list_node_t og_lnd; @@ -1255,6 +1257,7 @@ typedef struct smb_ofile { pid_t f_pid; uint32_t f_explicit_times; char f_quota_resume[SMB_SID_STRSZ]; + smb_oplock_grant_t f_oplock_grant; } smb_ofile_t; #define SMB_ODIR_MAGIC 0x4F444952 /* 'ODIR' */ -- 2.11.4.GIT