diff --git a/source3/auth/auth_util.c b/source3/auth/auth_util.c index 78f275d8672..51164256065 100644 --- a/source3/auth/auth_util.c +++ b/source3/auth/auth_util.c @@ -1107,6 +1107,7 @@ static NTSTATUS make_new_server_info_guest(auth_serversupplied_info **server_inf DOM_SID guest_sid; bool ret; char zeros[16]; + fstring tmp; if ( !(sampass = samu_new( NULL )) ) { return NT_STATUS_NO_MEMORY; @@ -1145,6 +1146,9 @@ static NTSTATUS make_new_server_info_guest(auth_serversupplied_info **server_inf (*server_info)->user_session_key = data_blob(zeros, sizeof(zeros)); (*server_info)->lm_session_key = data_blob(zeros, sizeof(zeros)); + alpha_strcpy(tmp, pdb_get_username(sampass), ". _-$", sizeof(tmp)); + (*server_info)->sanitized_username = talloc_strdup(*server_info, tmp); + return NT_STATUS_OK; } @@ -1200,6 +1204,12 @@ static auth_serversupplied_info *copy_serverinfo(auth_serversupplied_info *src) return NULL; } + dst->sanitized_username = talloc_strdup(dst, src->sanitized_username); + if (!dst->sanitized_username) { + TALLOC_FREE(dst); + return NULL; + } + return dst; } diff --git a/source3/include/auth.h b/source3/include/auth.h index a7531b35cd9..df2bed8756d 100644 --- a/source3/include/auth.h +++ b/source3/include/auth.h @@ -69,7 +69,15 @@ typedef struct auth_serversupplied_info { bool was_mapped; /* Did the username map match? */ char *unix_name; - + + /* + * For performance reasons we keep an alpha_strcpy-sanitized version + * of the username around as long as the global variable current_user + * still exists. If we did not do keep this, we'd have to call + * alpha_strcpy whenever we do a become_user(), potentially on every + * smb request. See set_current_user_info. + */ + char *sanitized_username; } auth_serversupplied_info; struct auth_context { diff --git a/source3/include/smb.h b/source3/include/smb.h index d1af77d1d61..47a11f51a08 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -1778,8 +1778,6 @@ typedef struct user_struct { struct user_struct *next, *prev; uint16 vuid; /* Tag for this entry. */ - userdom_struct user; - char *session_keystr; /* used by utmp and pam session code. TDB key string */ int homes_snum; diff --git a/source3/lib/substitute.c b/source3/lib/substitute.c index 62dfdb56b56..c8ad6199e8b 100644 --- a/source3/lib/substitute.c +++ b/source3/lib/substitute.c @@ -213,11 +213,18 @@ static const char *get_smb_user_name(void) /******************************************************************* Setup the strings used by substitutions. Called per packet. Ensure %U name is set correctly also. + + smb_name must be sanitized by alpha_strcpy ********************************************************************/ -void set_current_user_info(const userdom_struct *pcui) +void set_current_user_info(const char *smb_name, const char *unix_name, + const char *full_name, const char *domain) { - current_user_info = *pcui; + fstrcpy(current_user_info.smb_name, smb_name); + fstrcpy(current_user_info.unix_name, unix_name); + fstrcpy(current_user_info.full_name, full_name); + fstrcpy(current_user_info.domain, domain); + /* The following is safe as current_user_info.smb_name * has already been sanitised in register_existing_vuid. */ diff --git a/source3/printing/printing.c b/source3/printing/printing.c index c5fe53f0426..aa67f08d821 100644 --- a/source3/printing/printing.c +++ b/source3/printing/printing.c @@ -1989,7 +1989,8 @@ static bool is_owner(struct current_user *user, const char *servicename, return False; if ((vuser = get_valid_user_struct(user->vuid)) != NULL) { - return strequal(pjob->user, vuser->user.smb_name); + return strequal(pjob->user, + vuser->server_info->sanitized_username); } else { return strequal(pjob->user, uidtoname(user->ut.uid)); } @@ -2438,8 +2439,10 @@ uint32 print_job_start(struct current_user *user, int snum, char *jobname, NT_DE if ((vuser = get_valid_user_struct(user->vuid)) != NULL) { fstrcpy(pjob.user, lp_printjob_username(snum)); - standard_sub_basic(vuser->user.smb_name, vuser->user.domain, - pjob.user, sizeof(pjob.user)-1); + standard_sub_basic( + vuser->server_info->sanitized_username, + pdb_get_domain(vuser->server_info->sam_account), + pjob.user, sizeof(pjob.user)-1); /* ensure NULL termination */ pjob.user[sizeof(pjob.user)-1] = '\0'; } else { diff --git a/source3/rpc_server/srv_lsa_nt.c b/source3/rpc_server/srv_lsa_nt.c index 8bc377b97ea..7c33bd0d4f4 100644 --- a/source3/rpc_server/srv_lsa_nt.c +++ b/source3/rpc_server/srv_lsa_nt.c @@ -1479,8 +1479,8 @@ NTSTATUS _lsa_GetUserName(pipes_struct *p, return NT_STATUS_NO_MEMORY; } } else { - username = vuser->user.smb_name; - domname = vuser->user.domain; + username = vuser->server_info->sanitized_username; + domname = pdb_get_domain(vuser->server_info->sam_account); } account_name = TALLOC_ZERO_P(p->mem_ctx, struct lsa_String); diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index a3687451d5b..a2338934822 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -3340,7 +3340,7 @@ static bool api_RNetUserGetInfo(connection_struct *conn, uint16 vuid, if(vuser != NULL) { DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->server_info->uid, - vuser->user.unix_name)); + vuser->server_info->unix_name)); } if (!str1 || !str2 || !UserName || !p) { @@ -3413,7 +3413,9 @@ static bool api_RNetUserGetInfo(connection_struct *conn, uint16 vuid, /* EEK! the cifsrap.txt doesn't have this in!!!! */ SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */ - strlcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName),PTR_DIFF(endp,p2)); + strlcpy(p2,((vuser != NULL) + ? pdb_get_fullname(vuser->server_info->sam_account) + : UserName),PTR_DIFF(endp,p2)); p2 = skip_string(*rdata,*rdata_len,p2); if (!p2) { return False; @@ -3503,7 +3505,9 @@ static bool api_RNetUserGetInfo(connection_struct *conn, uint16 vuid, if (uLevel == 2) { SIVAL(p,60,0); /* auth_flags */ SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */ - strlcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName),PTR_DIFF(endp,p2)); + strlcpy(p2,((vuser != NULL) + ? pdb_get_fullname(vuser->server_info->sam_account) + : UserName),PTR_DIFF(endp,p2)); p2 = skip_string(*rdata,*rdata_len,p2); if (!p2) { return False; @@ -3592,7 +3596,7 @@ static bool api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, if(vuser != NULL) { DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->server_info->uid, - vuser->user.unix_name)); + vuser->server_info->unix_name)); } uLevel = get_safe_SVAL(param,tpscnt,p,0,-1); diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 5e2e713d439..a872ea2b489 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -253,40 +253,36 @@ int register_existing_vuid(uint16 vuid, DATA_BLOB response_blob, const char *smb_name) { - user_struct *vuser = get_partial_auth_user_struct(vuid); + fstring tmp; + user_struct *vuser; + + vuser = get_partial_auth_user_struct(vuid); if (!vuser) { goto fail; } /* Use this to keep tabs on all our info from the authentication */ - vuser->server_info = server_info; - - /* Ensure that the server_info will disappear with - * the vuser it is now attached to */ - - talloc_steal(vuser, vuser->server_info); - - fstrcpy(vuser->user.unix_name, server_info->unix_name); + vuser->server_info = talloc_move(vuser, &server_info); /* This is a potentially untrusted username */ - alpha_strcpy(vuser->user.smb_name, smb_name, ". _-$", - sizeof(vuser->user.smb_name)); + alpha_strcpy(tmp, smb_name, ". _-$", sizeof(tmp)); - fstrcpy(vuser->user.domain, pdb_get_domain(server_info->sam_account)); - fstrcpy(vuser->user.full_name, - pdb_get_fullname(server_info->sam_account)); + vuser->server_info->sanitized_username = talloc_strdup( + server_info, tmp); DEBUG(10,("register_existing_vuid: (%u,%u) %s %s %s guest=%d\n", - (unsigned int)vuser->server_info->uid, - (unsigned int)vuser->server_info->gid, - vuser->user.unix_name, vuser->user.smb_name, - vuser->user.domain, vuser->server_info->guest )); + (unsigned int)vuser->server_info->uid, + (unsigned int)vuser->server_info->gid, + vuser->server_info->unix_name, + vuser->server_info->sanitized_username, + pdb_get_domain(vuser->server_info->sam_account), + vuser->server_info->guest )); DEBUG(3, ("register_existing_vuid: User name: %s\t" - "Real name: %s\n", vuser->user.unix_name, - vuser->user.full_name)); + "Real name: %s\n", vuser->server_info->unix_name, + pdb_get_fullname(vuser->server_info->sam_account))); - if (!server_info->ptok) { + if (!vuser->server_info->ptok) { DEBUG(1, ("register_existing_vuid: server_info does not " "contain a user_token - cannot continue\n")); goto fail; @@ -294,7 +290,7 @@ int register_existing_vuid(uint16 vuid, DEBUG(3,("register_existing_vuid: UNIX uid %d is UNIX user %s, " "and will be vuid %u\n", (int)vuser->server_info->uid, - vuser->user.unix_name, vuser->vuid)); + vuser->server_info->unix_name, vuser->vuid)); next_vuid++; num_validated_vuids++; @@ -316,7 +312,7 @@ int register_existing_vuid(uint16 vuid, if (!vuser->server_info->guest) { vuser->homes_snum = register_homes_share( - vuser->user.unix_name); + vuser->server_info->unix_name); } if (srv_is_signing_negotiated() && !vuser->server_info->guest && @@ -327,7 +323,12 @@ int register_existing_vuid(uint16 vuid, } /* fill in the current_user_info struct */ - set_current_user_info( &vuser->user ); + set_current_user_info( + vuser->server_info->sanitized_username, + vuser->server_info->unix_name, + pdb_get_fullname(vuser->server_info->sam_account), + pdb_get_domain(vuser->server_info->sam_account)); + return vuser->vuid; fail: diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 5946989ae75..ab737a89a7e 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1387,7 +1387,13 @@ static connection_struct *switch_message(uint8 type, struct smb_request *req, in if(session_tag != UID_FIELD_INVALID) { vuser = get_valid_user_struct(session_tag); if (vuser) { - set_current_user_info(&vuser->user); + set_current_user_info( + vuser->server_info->sanitized_username, + vuser->server_info->unix_name, + pdb_get_fullname(vuser->server_info + ->sam_account), + pdb_get_domain(vuser->server_info + ->sam_account)); } } } diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 7b0fdc89767..ff69fc4029f 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -724,11 +724,12 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, return NULL; } } else { - if (!user_ok_token(vuser->user.unix_name, + if (!user_ok_token(vuser->server_info->unix_name, vuser->server_info->ptok, snum)) { DEBUG(2, ("user '%s' (from session setup) not " "permitted to access this share " - "(%s)\n", vuser->user.unix_name, + "(%s)\n", + vuser->server_info->unix_name, lp_servicename(snum))); conn_free(conn); *status = NT_STATUS_ACCESS_DENIED; @@ -738,8 +739,8 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, conn->vuid = vuser->vuid; conn->uid = vuser->server_info->uid; conn->gid = vuser->server_info->gid; - string_set(&conn->user,vuser->user.unix_name); - fstrcpy(user,vuser->user.unix_name); + string_set(&conn->user,vuser->server_info->unix_name); + fstrcpy(user,vuser->server_info->unix_name); guest = vuser->server_info->guest; } else if (lp_security() == SEC_SHARE) { NTSTATUS status2; diff --git a/source3/smbd/session.c b/source3/smbd/session.c index 2b964d828f9..5e5a184efaf 100644 --- a/source3/smbd/session.c +++ b/source3/smbd/session.c @@ -164,7 +164,7 @@ bool session_claim(user_struct *vuser) hostname = client_addr(get_client_fd(),addr,sizeof(addr)); } - fstrcpy(sessionid.username, vuser->user.unix_name); + fstrcpy(sessionid.username, vuser->server_info->unix_name); fstrcpy(sessionid.hostname, hostname); sessionid.id_num = i; /* Only valid for utmp sessions */ sessionid.pid = pid; diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 0b87b93636c..3779c3f6088 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -97,12 +97,14 @@ static bool check_user_ok(connection_struct *conn, user_struct *vuser,int snum) } } - if (!user_ok_token(vuser->user.unix_name, vuser->server_info->ptok, + if (!user_ok_token(vuser->server_info->unix_name, + vuser->server_info->ptok, snum)) return(False); readonly_share = is_share_read_only_for_token( - vuser->user.unix_name, vuser->server_info->ptok, SNUM(conn)); + vuser->server_info->unix_name, vuser->server_info->ptok, + SNUM(conn)); token = conn->nt_user_token ? conn->nt_user_token : vuser->server_info->ptok; @@ -132,7 +134,7 @@ static bool check_user_ok(connection_struct *conn, user_struct *vuser,int snum) ent->read_only = readonly_share; ent->admin_user = token_contains_name_in_list( - vuser->user.unix_name, NULL, vuser->server_info->ptok, + vuser->server_info->unix_name, NULL, vuser->server_info->ptok, lp_admin_users(SNUM(conn))); conn->read_only = ent->read_only; @@ -188,7 +190,8 @@ bool change_to_user(connection_struct *conn, uint16 vuid) if ((vuser) && !check_user_ok(conn, vuser, snum)) { DEBUG(2,("change_to_user: SMB user %s (unix user %s, vuid %d) " "not permitted access to share %s.\n", - vuser->user.smb_name, vuser->user.unix_name, vuid, + vuser->server_info->sanitized_username, + vuser->server_info->unix_name, vuid, lp_servicename(snum))); return False; }