From f87399915b009f88c41cb75a583c2972fe3daf30 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 3 Aug 2000 22:38:43 +0000 Subject: Added an NT_USER_TOKEN structure that is copied/passed around associated with the current user. This will allow se_access_check() to quickly do a SD check without having to translate uid/gid's to SIDs. Still needs work on pipe calls. Jeremy. (This used to be commit e28d01b744b3dbd33e0e54af4e7f426fa8c082b8) --- source3/include/proto.h | 4 +- source3/include/smb.h | 12 ++++- source3/include/vfs.h | 49 +++++++++++++++++ source3/lib/util_sid.c | 8 +-- source3/smbd/conn.c | 5 +- source3/smbd/password.c | 27 +++++----- source3/smbd/sec_ctx.c | 98 +++++++++++++++++++++++++++++----- source3/smbd/service.c | 138 +++++++++++++++++++++++++----------------------- source3/smbd/uid.c | 8 +-- 9 files changed, 246 insertions(+), 103 deletions(-) diff --git a/source3/include/proto.h b/source3/include/proto.h index 321f3098e9..e630d7019f 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -3546,7 +3546,6 @@ void invalidate_vuid(uint16 vuid); char *validated_username(uint16 vuid); char *validated_domain(uint16 vuid); int initialize_groups(char *user, uid_t uid, gid_t gid); -void setup_nt_token(NT_USER_TOKEN *token, uid_t uid, gid_t gid, int ngroups, gid_t *groups); uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, char *domain,BOOL guest); void add_session_user(char *user); @@ -3673,8 +3672,9 @@ int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, /*The following definitions come from smbd/sec_ctx.c */ int get_current_groups(int *p_ngroups, gid_t **p_groups); +void delete_nt_token(NT_USER_TOKEN **pptoken); BOOL push_sec_ctx(void); -void set_sec_ctx(uid_t uid, gid_t gid, int ngroups, gid_t *groups); +void set_sec_ctx(uid_t uid, gid_t gid, int ngroups, gid_t *groups, NT_USER_TOKEN *token); void set_root_sec_ctx(void); BOOL pop_sec_ctx(void); void init_sec_ctx(void); diff --git a/source3/include/smb.h b/source3/include/smb.h index aaebe56f33..03d4b4c9b3 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -383,8 +383,11 @@ struct use_info char *domain; }; +#ifndef MAXSUBAUTHS #define MAXSUBAUTHS 15 /* max sub authorities in a SID */ +#endif +#ifndef _DOM_SID /* DOM_SID - security id */ typedef struct sid_info { @@ -398,16 +401,21 @@ typedef struct sid_info uint32 sub_auths[MAXSUBAUTHS]; /* pointer to sub-authorities. */ } DOM_SID; +#define _DOM_SID +#endif /* * The complete list of SIDS belonging to this user. * Created when a vuid is registered. */ +#ifndef _NT_USER_TOKEN typedef struct _nt_user_token { size_t num_sids; DOM_SID *user_sids; } NT_USER_TOKEN; +#define _NT_USER_TOKEN +#endif /*** query a local group, get a list of these: shows who is in that group ***/ @@ -580,6 +588,7 @@ typedef struct connection_struct /* This groups info is valid for the user that *opened* the connection */ int ngroups; gid_t *groups; + NT_USER_TOKEN *nt_user_token; time_t lastused; BOOL used; @@ -598,6 +607,7 @@ struct current_user gid_t gid; int ngroups; gid_t *groups; + NT_USER_TOKEN *nt_user_token; }; /* @@ -1672,7 +1682,7 @@ typedef struct int n_groups; gid_t *groups; - NT_USER_TOKEN nt_user_token; + NT_USER_TOKEN *nt_user_token; /* per-user authentication information on NT RPCs */ /* lkclXXXX - THIS SHOULD NOT BE HERE! */ diff --git a/source3/include/vfs.h b/source3/include/vfs.h index 1b4e57f2ac..1312935e7f 100644 --- a/source3/include/vfs.h +++ b/source3/include/vfs.h @@ -64,6 +64,54 @@ typedef char fstring[FSTRING_LEN]; #define SMB_BIG_UINT unsigned long #endif +#ifndef MAXSUBAUTHS +#define MAXSUBAUTHS 15 /* max sub authorities in a SID */ +#endif + +#ifndef uint8 +#define uint8 unsigned char +#endif + +#if !defined(uint32) && !defined(HAVE_UINT32_FROM_RPC_RPC_H) +#if (SIZEOF_INT == 4) +#define uint32 unsigned int +#elif (SIZEOF_LONG == 4) +#define uint32 unsigned long +#elif (SIZEOF_SHORT == 4) +#define uint32 unsigned short +#endif +#endif + +#ifndef _DOM_SID +/* DOM_SID - security id */ +typedef struct sid_info +{ + uint8 sid_rev_num; /* SID revision number */ + uint8 num_auths; /* number of sub-authorities */ + uint8 id_auth[6]; /* Identifier Authority */ + /* + * Note that the values in these uint32's are in *native* byteorder, + * not neccessarily little-endian...... JRA. + */ + uint32 sub_auths[MAXSUBAUTHS]; /* pointer to sub-authorities. */ + +} DOM_SID; +#define _DOM_SID +#endif + +/* + * The complete list of SIDS belonging to this user. + * Created when a vuid is registered. + */ + +#ifndef _NT_USER_TOKEN +typedef struct _nt_user_token { + size_t num_sids; + DOM_SID *user_sids; +} NT_USER_TOKEN; +#define _NT_USER_TOKEN +#endif + /* Information from the connection_struct passed to the vfs layer */ struct vfs_connection_struct { @@ -93,6 +141,7 @@ struct vfs_connection_struct { gid_t gid; int ngroups; gid_t *groups; + NT_USER_TOKEN *nt_user_token; }; /* Avoid conflict with an AIX include file */ diff --git a/source3/lib/util_sid.c b/source3/lib/util_sid.c index 3572f2c775..52e9f63039 100644 --- a/source3/lib/util_sid.c +++ b/source3/lib/util_sid.c @@ -33,13 +33,14 @@ extern fstring global_myworkgroup; * Some useful sids */ -DOM_SID global_sid_S_1_5_0x20; /* local well-known domain */ +DOM_SID global_sid_Builtin; /* local well-known domain */ DOM_SID global_sid_World_Domain; /* everyone */ DOM_SID global_sid_World; /* everyone */ DOM_SID global_sid_Creator_Owner_Domain; /* Creator Owner */ DOM_SID global_sid_Creator_Owner; /* Creator Owner */ DOM_SID global_sid_NT_Authority; /* NT Authority */ DOM_SID global_sid_NULL; /* NULL sid */ +DOM_SID global_sid_Builtin_Guests; const DOM_SID *global_sid_everyone = &global_sid_World; @@ -75,7 +76,7 @@ sid_name_map[] = { { &global_sam_sid, global_myname, NULL}, { &global_sam_sid, global_myworkgroup, NULL}, - { &global_sid_S_1_5_0x20, "BUILTIN", NULL}, + { &global_sid_Builtin, "BUILTIN", NULL}, { &global_sid_World_Domain, "", &everyone_users[0] }, { &global_sid_Creator_Owner_Domain, "", &creator_owner_users[0] }, { &global_sid_NT_Authority, "NT Authority", &nt_authority_users[0] }, @@ -88,7 +89,8 @@ sid_name_map[] = void generate_wellknown_sids(void) { - string_to_sid(&global_sid_S_1_5_0x20, "S-1-5-32"); + string_to_sid(&global_sid_Builtin, "S-1-5-32"); + string_to_sid(&global_sid_Builtin_Guests, "S-1-5-32-546"); string_to_sid(&global_sid_World_Domain, "S-1-1"); string_to_sid(&global_sid_World, "S-1-1-0"); string_to_sid(&global_sid_Creator_Owner_Domain, "S-1-3"); diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index 0e74b62ee0..c1f42be098 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -162,8 +162,9 @@ BOOL conn_idle_all(time_t t, int deadtime) } /**************************************************************************** -free a conn structure + Free a conn structure. ****************************************************************************/ + void conn_free(connection_struct *conn) { /* Free vfs_connection_struct */ @@ -179,6 +180,7 @@ void conn_free(connection_struct *conn) if (conn->vfs_conn->groups != NULL) { free(conn->vfs_conn->groups); } + delete_nt_token(&conn->vfs_conn->nt_user_token); free(conn->vfs_conn); } @@ -190,6 +192,7 @@ void conn_free(connection_struct *conn) conn->ngroups = 0; } + delete_nt_token(&conn->nt_user_token); free_namearray(conn->veto_list); free_namearray(conn->hide_list); free_namearray(conn->veto_oplock_list); diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 0372e7a0f9..9af7d3b1e9 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -112,16 +112,6 @@ user_struct *get_valid_user_struct(uint16 vuid) return &validated_users[vuid]; } -/**************************************************************************** - Delete the SID list for this user. -****************************************************************************/ - -static void delete_nt_token(NT_USER_TOKEN *token) -{ - safe_free( token->user_sids ); - ZERO_STRUCTP(token); -} - /**************************************************************************** invalidate a uid ****************************************************************************/ @@ -146,7 +136,6 @@ void invalidate_vuid(uint16 vuid) delete_nt_token(&vuser->nt_user_token); } - /**************************************************************************** return a validated username ****************************************************************************/ @@ -192,15 +181,21 @@ int initialize_groups(char *user, uid_t uid, gid_t gid) Create the SID list for this user. ****************************************************************************/ -void setup_nt_token(NT_USER_TOKEN *token, uid_t uid, gid_t gid, int ngroups, gid_t *groups) +NT_USER_TOKEN *create_nt_token(uid_t uid, gid_t gid, int ngroups, gid_t *groups) { + NT_USER_TOKEN *token; DOM_SID *psids; int i; + if ((token = (NT_USER_TOKEN *)malloc( sizeof(NT_USER_TOKEN) ) ) == NULL) + return NULL; + ZERO_STRUCTP(token); - if ((token->user_sids = (DOM_SID *)malloc( (ngroups + 2)*sizeof(DOM_SID))) == NULL) - return; + if ((token->user_sids = (DOM_SID *)malloc( (ngroups + 2)*sizeof(DOM_SID))) == NULL) { + free(token); + return NULL; + } psids = token->user_sids; @@ -211,6 +206,8 @@ void setup_nt_token(NT_USER_TOKEN *token, uid_t uid, gid_t gid, int ngroups, gid for (i = 0; i < ngroups; i++) gid_to_sid( &psids[i+2], groups[i]); + + return token; } /**************************************************************************** @@ -258,7 +255,7 @@ uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, get_current_groups( &vuser->n_groups, &vuser->groups); /* Create an NT_USER_TOKEN struct for this user. */ - setup_nt_token(&vuser->nt_user_token, uid,gid, vuser->n_groups, vuser->groups); + vuser->nt_user_token = create_nt_token(uid,gid, vuser->n_groups, vuser->groups); DEBUG(3,("uid %d registered to name %s\n",(int)uid,unix_name)); diff --git a/source3/smbd/sec_ctx.c b/source3/smbd/sec_ctx.c index 432cb223e2..118c2f46b6 100644 --- a/source3/smbd/sec_ctx.c +++ b/source3/smbd/sec_ctx.c @@ -29,6 +29,7 @@ struct sec_ctx { uid_t gid; int ngroups; gid_t *groups; + NT_USER_TOKEN *token; }; /* A stack of security contexts. We include the current context as being @@ -37,7 +38,9 @@ struct sec_ctx { static struct sec_ctx sec_ctx_stack[MAX_SEC_CTX_DEPTH + 1]; static int sec_ctx_stack_ndx; -/* Become the specified uid */ +/**************************************************************************** + Become the specified uid. +****************************************************************************/ static BOOL become_uid(uid_t uid) { @@ -66,7 +69,9 @@ static BOOL become_uid(uid_t uid) return True; } -/* Become the specified gid */ +/**************************************************************************** + Become the specified gid. +****************************************************************************/ static BOOL become_gid(gid_t gid) { @@ -91,14 +96,18 @@ static BOOL become_gid(gid_t gid) return True; } -/* Become the specified uid and gid */ +/**************************************************************************** + Become the specified uid and gid. +****************************************************************************/ static BOOL become_id(uid_t uid, gid_t gid) { return become_gid(gid) && become_uid(uid); } -/* Drop back to root privileges in order to change to another user */ +/**************************************************************************** + Drop back to root privileges in order to change to another user. +****************************************************************************/ static void gain_root(void) { @@ -123,7 +132,9 @@ static void gain_root(void) } } -/* Get the list of current groups */ +/**************************************************************************** + Get the list of current groups. +****************************************************************************/ int get_current_groups(int *p_ngroups, gid_t **p_groups) { @@ -158,8 +169,51 @@ int get_current_groups(int *p_ngroups, gid_t **p_groups) return ngroups; } -/* Create a new security context on the stack. It is the same as the old - one. User changes are done using the set_sec_ctx() function. */ +/**************************************************************************** + Delete a SID token. +****************************************************************************/ + +void delete_nt_token(NT_USER_TOKEN **pptoken) +{ + if (*pptoken) { + NT_USER_TOKEN *ptoken = *pptoken; + safe_free( ptoken->user_sids ); + ZERO_STRUCTP(ptoken); + } + safe_free(*pptoken); + *pptoken = NULL; +} + +/**************************************************************************** + Duplicate a SID token. +****************************************************************************/ + +NT_USER_TOKEN *dup_nt_token(NT_USER_TOKEN *ptoken) +{ + NT_USER_TOKEN *token; + + if (!ptoken) + return NULL; + + if ((token = (NT_USER_TOKEN *)malloc( sizeof(NT_USER_TOKEN) ) ) == NULL) + return NULL; + + ZERO_STRUCTP(token); + + if ((token->user_sids = (DOM_SID *)memdup( ptoken->user_sids, sizeof(DOM_SID) * ptoken->num_sids )) == NULL) { + free(token); + return NULL; + } + + token->num_sids = ptoken->num_sids; + + return token; +} + +/**************************************************************************** + Create a new security context on the stack. It is the same as the old + one. User changes are done using the set_sec_ctx() function. +****************************************************************************/ BOOL push_sec_ctx(void) { @@ -181,11 +235,14 @@ BOOL push_sec_ctx(void) ctx_p->uid = geteuid(); ctx_p->gid = getegid(); + ctx_p->token = dup_nt_token(sec_ctx_stack[sec_ctx_stack_ndx-1].token); + ctx_p->ngroups = sys_getgroups(0, NULL); if (ctx_p->ngroups != 0) { if (!(ctx_p->groups = malloc(ctx_p->ngroups * sizeof(gid_t)))) { DEBUG(0, ("Out of memory in push_sec_ctx()\n")); + delete_nt_token(&ctx_p->token); return False; } @@ -197,9 +254,11 @@ BOOL push_sec_ctx(void) return True; } -/* Set the current security context to a given user */ +/**************************************************************************** + Set the current security context to a given user. +****************************************************************************/ -void set_sec_ctx(uid_t uid, gid_t gid, int ngroups, gid_t *groups) +void set_sec_ctx(uid_t uid, gid_t gid, int ngroups, gid_t *groups, NT_USER_TOKEN *token) { struct sec_ctx *ctx_p = &sec_ctx_stack[sec_ctx_stack_ndx]; @@ -216,8 +275,10 @@ void set_sec_ctx(uid_t uid, gid_t gid, int ngroups, gid_t *groups) ctx_p->ngroups = ngroups; safe_free(ctx_p->groups); - + delete_nt_token(&ctx_p->token); + ctx_p->groups = memdup(groups, sizeof(gid_t) * ngroups); + ctx_p->token = dup_nt_token(token); become_id(uid, gid); @@ -230,18 +291,23 @@ void set_sec_ctx(uid_t uid, gid_t gid, int ngroups, gid_t *groups) current_user.gid = gid; current_user.ngroups = ngroups; current_user.groups = groups; + current_user.nt_user_token = token; } -/* Become root context */ +/**************************************************************************** + Become root context. +****************************************************************************/ void set_root_sec_ctx(void) { /* May need to worry about supplementary groups at some stage */ - set_sec_ctx(0, 0, 0, NULL); + set_sec_ctx(0, 0, 0, NULL, NULL); } -/* Pop a security context from the stack */ +/**************************************************************************** + Pop a security context from the stack. +****************************************************************************/ BOOL pop_sec_ctx(void) { @@ -265,6 +331,8 @@ BOOL pop_sec_ctx(void) safe_free(ctx_p->groups); ctx_p->ngroups = 0; + delete_nt_token(&ctx_p->token); + /* Pop back previous user */ sec_ctx_stack_ndx--; @@ -285,6 +353,7 @@ BOOL pop_sec_ctx(void) current_user.gid = prev_ctx_p->gid; current_user.ngroups = prev_ctx_p->ngroups; current_user.groups = prev_ctx_p->groups; + current_user.nt_user_token = prev_ctx_p->token; DEBUG(3, ("popped off to sec ctx (%d, %d)\n", geteuid(), getegid())); @@ -315,6 +384,8 @@ void init_sec_ctx(void) get_current_groups(&ctx_p->ngroups, &ctx_p->groups); + ctx_p->token = NULL; /* Maps to guest user. */ + /* Initialise current_user global */ current_user.uid = ctx_p->uid; @@ -327,4 +398,5 @@ void init_sec_ctx(void) current_user.conn = NULL; current_user.vuid = UID_FIELD_INVALID; + current_user.nt_user_token = NULL; } diff --git a/source3/smbd/service.c b/source3/smbd/service.c index d4760ca92d..8b63fe6662 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -360,65 +360,8 @@ connection_struct *make_connection(char *service,char *user,char *password, int conn->veto_oplock_list = NULL; string_set(&conn->dirpath,""); string_set(&conn->user,user); + conn->nt_user_token = NULL; - conn->vfs_conn = (struct vfs_connection_struct *) - malloc(sizeof(struct vfs_connection_struct)); - - if (conn->vfs_conn == NULL) { - DEBUG(0, ("No memory to create vfs_connection_struct")); - return NULL; - } - - ZERO_STRUCTP(conn->vfs_conn); - - /* Copy across relevant data from connection struct */ - - conn->vfs_conn->printer = conn->printer; - conn->vfs_conn->ipc = conn->ipc; - conn->vfs_conn->read_only = conn->read_only; - conn->vfs_conn->admin_user = conn->admin_user; - - pstrcpy(conn->vfs_conn->dirpath, conn->dirpath); - pstrcpy(conn->vfs_conn->connectpath, conn->connectpath); - pstrcpy(conn->vfs_conn->origpath, conn->origpath); - - pstrcpy(conn->vfs_conn->service, service); - pstrcpy(conn->vfs_conn->user, conn->user); - - conn->vfs_conn->uid = conn->uid; - conn->vfs_conn->gid = conn->gid; - conn->vfs_conn->ngroups = conn->ngroups; - if (conn->vfs_conn->ngroups != 0) { - conn->vfs_conn->groups = (gid_t *)memdup(conn->groups, - conn->ngroups * sizeof(gid_t)); - } else { - conn->vfs_conn->groups = NULL; - } - - /* Initialise VFS function pointers */ - - if (*lp_vfsobj(SNUM(conn))) { - -#ifdef HAVE_LIBDL - - /* Loadable object file */ - - if (!vfs_init_custom(conn)) { - return NULL; - } -#else - DEBUG(0, ("No libdl present - cannot use VFS objects\n")); - conn_free(conn); - return NULL; -#endif - - } else { - - /* Normal share - initialise with disk access functions */ - - vfs_init_default(conn); - } - /* * If force user is true, then store the * given userid and also the primary groupid @@ -529,7 +472,73 @@ connection_struct *make_connection(char *service,char *user,char *password, int claim_connection(conn,"", MAXSTATUS,False); } /* IS_IPC */ - + + conn->nt_user_token = create_nt_token(conn->uid, conn->gid, conn->ngroups, conn->groups); + + /* + * Now initialize the vfs layer. + */ + + conn->vfs_conn = (struct vfs_connection_struct *) + malloc(sizeof(struct vfs_connection_struct)); + + if (conn->vfs_conn == NULL) { + DEBUG(0, ("No memory to create vfs_connection_struct")); + return NULL; + } + + ZERO_STRUCTP(conn->vfs_conn); + + /* Copy across relevant data from connection struct */ + + conn->vfs_conn->printer = conn->printer; + conn->vfs_conn->ipc = conn->ipc; + conn->vfs_conn->read_only = conn->read_only; + conn->vfs_conn->admin_user = conn->admin_user; + + pstrcpy(conn->vfs_conn->dirpath, conn->dirpath); + pstrcpy(conn->vfs_conn->connectpath, conn->connectpath); + pstrcpy(conn->vfs_conn->origpath, conn->origpath); + + pstrcpy(conn->vfs_conn->service, service); + pstrcpy(conn->vfs_conn->user, conn->user); + + conn->vfs_conn->uid = conn->uid; + conn->vfs_conn->gid = conn->gid; + conn->vfs_conn->ngroups = conn->ngroups; + if (conn->vfs_conn->ngroups != 0) { + conn->vfs_conn->groups = (gid_t *)memdup(conn->groups, + conn->ngroups * sizeof(gid_t)); + } else { + conn->vfs_conn->groups = NULL; + } + + conn->vfs_conn->nt_user_token = dup_nt_token(conn->nt_user_token); + + /* Initialise VFS function pointers */ + + if (*lp_vfsobj(SNUM(conn))) { + +#ifdef HAVE_LIBDL + + /* Loadable object file */ + + if (!vfs_init_custom(conn)) { + return NULL; + } +#else + DEBUG(0, ("No libdl present - cannot use VFS objects\n")); + conn_free(conn); + return NULL; +#endif + + } else { + + /* Normal share - initialise with disk access functions */ + + vfs_init_default(conn); + } + /* execute any "root preexec = " line */ if (*lp_rootpreexec(SNUM(conn))) { pstring cmd; @@ -630,13 +639,12 @@ connection_struct *make_connection(char *service,char *user,char *password, int /* Invoke VFS make connection hook */ - if (conn->vfs_ops.connect) { - if (conn->vfs_ops.connect(conn->vfs_conn, service, user) < 0) { - return NULL; - } - } + if (conn->vfs_ops.connect) { + if (conn->vfs_ops.connect(conn->vfs_conn, service, user) < 0) + return NULL; + } - return(conn); + return(conn); } diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 4cb2c512b6..f6687e9a5a 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -47,7 +47,7 @@ BOOL become_guest(void) initgroups(pass->pw_name, (gid_t)pass->pw_gid); #endif - set_sec_ctx(pass->pw_uid, pass->pw_gid, 0, NULL); + set_sec_ctx(pass->pw_uid, pass->pw_gid, 0, NULL, NULL); current_user.conn = NULL; current_user.vuid = UID_FIELD_INVALID; @@ -164,10 +164,11 @@ BOOL become_user(connection_struct *conn, uint16 vuid) } } - set_sec_ctx(uid, gid, current_user.ngroups, current_user.groups); + set_sec_ctx(uid, gid, current_user.ngroups, current_user.groups, current_user.nt_user_token); current_user.conn = conn; current_user.vuid = vuid; + current_user.nt_user_token = conn->nt_user_token; DEBUG(5,("become_user uid=(%d,%d) gid=(%d,%d)\n", (int)getuid(),(int)geteuid(),(int)getgid(),(int)getegid())); @@ -206,8 +207,9 @@ BOOL become_authenticated_pipe_user(pipes_struct *p) return False; } + /* JRATEST - this needs fixined w.r.t. NT user tokens... */ set_sec_ctx(p->pipe_user.uid, p->pipe_user.gid, - p->pipe_user.ngroups, p->pipe_user.groups); + p->pipe_user.ngroups, p->pipe_user.groups, NULL); return True; } -- cgit