diff options
author | Luke Leighton <lkcl@samba.org> | 2000-02-06 05:17:28 +0000 |
---|---|---|
committer | Luke Leighton <lkcl@samba.org> | 2000-02-06 05:17:28 +0000 |
commit | cf34c0bec59dfd8b83edf3e111e925ccd3db1226 (patch) | |
tree | c68c44f0f3c93c46845e6fd4183b99328d4154d5 /source/smbd | |
parent | 28aa3f66138b8be02d8198537b0e524b4b6b417b (diff) | |
download | samba-cf34c0bec59dfd8b83edf3e111e925ccd3db1226.tar.gz |
this is probably one of THE most reluctant commits i've ever made.
it's far-reaching, and necessary.
this adds a vuser_struct tdb database, with a key [smbd's pid, vuid].
smbd uses it in every instance of standard_sub() and standard_sub_vuser().
that's almost every single SMB call for any IPC$ access.
the next stage is to remove sesssetup_user, probably sessetup_user_list too,
and review all occurences of standard_sub_basic used by smbd because if
they use standard_sub_basic() they might be expecting to read sesssetup_user,
and if they do _that_, they should be using standard_sub_vuser() instead.
all i wanted was a means to get vuids across to msrpc daemons.
Diffstat (limited to 'source/smbd')
-rw-r--r-- | source/smbd/lanman.c | 128 | ||||
-rw-r--r-- | source/smbd/open.c | 4 | ||||
-rw-r--r-- | source/smbd/oplock.c | 2 | ||||
-rw-r--r-- | source/smbd/password.c | 266 | ||||
-rw-r--r-- | source/smbd/process.c | 10 | ||||
-rw-r--r-- | source/smbd/reply.c | 19 | ||||
-rw-r--r-- | source/smbd/service.c | 56 | ||||
-rw-r--r-- | source/smbd/uid.c | 35 |
8 files changed, 327 insertions, 193 deletions
diff --git a/source/smbd/lanman.c b/source/smbd/lanman.c index 84387bd178d..37b71f9b159 100644 --- a/source/smbd/lanman.c +++ b/source/smbd/lanman.c @@ -1,12 +1,14 @@ -/* + /* Unix SMB/Netbios implementation. Version 1.9. Inter-process communication and named pipe handling - Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) Andrew Tridgell 1992-2000 SMB Version handling - Copyright (C) John H Terpstra 1995-1998 - + Copyright (C) John H Terpstra 1995-2000 + + Copyright (C) Luke Kenneth Casson Leighton 1996-2000 + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or @@ -73,17 +75,21 @@ static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char * int *rdata_len,int *rparam_len); -static int CopyExpanded(connection_struct *conn, uint16 vuid, +static int CopyExpanded(connection_struct *conn, const vuser_key *key, int snum, char** dst, char* src, int* n) { pstring buf; int l; + user_struct *vuser; if (!src || !dst || !n || !(*dst)) return(0); StrnCpy(buf,src,sizeof(buf)/2); string_sub(buf,"%S",lp_servicename(snum)); - standard_sub(conn,get_valid_user_struct(vuid), buf); + vuser = get_valid_user_struct(key); + standard_sub(conn,vuser, buf); + vuid_free_user_struct(vuser); + safe_free(vuser); StrnCpy(*dst,buf,*n); l = strlen(*dst) + 1; (*dst) += l; @@ -103,23 +109,29 @@ static int CopyAndAdvance(char** dst, char* src, int* n) } static int StrlenExpanded(connection_struct *conn, - uint16 vuid, int snum, char* s) + const vuser_key *key, int snum, char* s) { + user_struct *vuser; pstring buf; if (!s) return(0); StrnCpy(buf,s,sizeof(buf)/2); string_sub(buf,"%S",lp_servicename(snum)); - standard_sub(conn,get_valid_user_struct(vuid), buf); + vuser = get_valid_user_struct(key); + standard_sub(conn,vuser, buf); + vuid_free_user_struct(vuser); + safe_free(vuser); return strlen(buf) + 1; } -static char* Expand(connection_struct *conn, uint16 vuid, int snum, char* s) +static char* Expand(connection_struct *conn, const vuser_key *key, int snum, char* s) { + user_struct *vuser; static pstring buf; if (!s) return(NULL); StrnCpy(buf,s,sizeof(buf)/2); string_sub(buf,"%S",lp_servicename(snum)); - standard_sub(conn,get_valid_user_struct(vuid), buf); + vuser = get_valid_user_struct(key); + standard_sub(conn,vuser, buf); return &buf[0]; } @@ -446,7 +458,7 @@ static void fill_printjob_info(connection_struct *conn, } } -static void fill_printq_info(connection_struct *conn, uint16 vuid, +static void fill_printq_info(connection_struct *conn, const vuser_key *key, int snum, int uLevel, struct pack_desc* desc, int count, print_queue_struct* queue, @@ -460,7 +472,7 @@ static void fill_printq_info(connection_struct *conn, uint16 vuid, case 3: case 4: case 5: - PACKS(desc,"z",Expand(conn,vuid, snum,SERVICE(snum))); + PACKS(desc,"z",Expand(conn,key, snum,SERVICE(snum))); break; } @@ -478,7 +490,7 @@ static void fill_printq_info(connection_struct *conn, uint16 vuid, PACKI(desc,"W",LPSTAT_ERROR); } else if (!status || !status->message[0]) { - PACKS(desc,"z",Expand(conn,vuid, snum,lp_comment(snum))); + PACKS(desc,"z",Expand(conn,key, snum,lp_comment(snum))); PACKI(desc,"W",LPSTAT_OK); /* status */ } else { PACKS(desc,"z",status->message); @@ -495,7 +507,7 @@ static void fill_printq_info(connection_struct *conn, uint16 vuid, PACKS(desc,"z","WinPrint"); /* pszPrProc */ PACKS(desc,"z",""); /* pszParms */ if (!status || !status->message[0]) { - PACKS(desc,"z",Expand(conn,vuid, snum,lp_comment(snum))); /* pszComment */ + PACKS(desc,"z",Expand(conn,key, snum,lp_comment(snum))); /* pszComment */ PACKI(desc,"W",LPSTAT_OK); /* fsStatus */ } else { PACKS(desc,"z",status->message); /* pszComment */ @@ -686,6 +698,7 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn, struct pack_desc desc; print_queue_struct *queue=NULL; print_status_struct status; + vuser_key key = { conn->smbd_pid, vuid }; bzero(&status,sizeof(status)); bzero(&desc,sizeof(desc)); @@ -718,7 +731,7 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn, count = get_printerdrivernumber(snum); DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count)); } else { - count = get_printqueue(snum, conn,vuid,&queue,&status); + count = get_printqueue(snum, conn,&key,&queue,&status); } if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); @@ -726,7 +739,7 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn, desc.buflen = mdrcnt; if (init_package(&desc,1,count)) { desc.subcount = count; - fill_printq_info(conn,vuid,snum,uLevel,&desc,count,queue,&status); + fill_printq_info(conn,&key,snum,uLevel,&desc,count,queue,&status); } else if (uLevel == 0) { /* * This is a *disgusting* hack. @@ -785,6 +798,7 @@ static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param, print_status_struct *status = NULL; int* subcntarr = NULL; int queuecnt, subcnt=0, succnt=0; + vuser_key key = { conn->smbd_pid, vuid }; bzero(&desc,sizeof(desc)); @@ -816,7 +830,7 @@ static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param, n = 0; for (i = 0; i < services; i++) if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) { - subcntarr[n] = get_printqueue(i, conn, vuid, &queue[n],&status[n]); + subcntarr[n] = get_printqueue(i, conn, &key, &queue[n],&status[n]); subcnt += subcntarr[n]; n++; } @@ -830,7 +844,7 @@ static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param, succnt = 0; for (i = 0; i < services; i++) if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) { - fill_printq_info(conn,vuid, i,uLevel,&desc,subcntarr[n],queue[n],&status[n]); + fill_printq_info(conn,&key, i,uLevel,&desc,subcntarr[n],queue[n],&status[n]); n++; if (desc.errcode == NERR_Success) succnt = n; } @@ -1269,7 +1283,7 @@ static BOOL check_share_info(int uLevel, char* id) return True; } -static int fill_share_info(connection_struct *conn, uint16 vuid, +static int fill_share_info(connection_struct *conn, const vuser_key *key, int snum, int uLevel, char** buf, int* buflen, char** stringbuf, int* stringspace, char* baseaddr) @@ -1292,7 +1306,7 @@ static int fill_share_info(connection_struct *conn, uint16 vuid, if (!buf) { len = 0; - if (uLevel > 0) len += StrlenExpanded(conn,vuid,snum,lp_comment(snum)); + if (uLevel > 0) len += StrlenExpanded(conn,key,snum,lp_comment(snum)); if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1; if (buflen) *buflen = struct_len; if (stringspace) *stringspace = len; @@ -1325,7 +1339,7 @@ static int fill_share_info(connection_struct *conn, uint16 vuid, if (strequal("IPC$",lp_servicename(snum))) type = STYPE_IPC; SSVAL(p,14,type); /* device type */ SIVAL(p,16,PTR_DIFF(p2,baseaddr)); - len += CopyExpanded(conn,vuid, snum,&p2,lp_comment(snum),&l2); + len += CopyExpanded(conn,key, snum,&p2,lp_comment(snum),&l2); } if (uLevel > 1) @@ -1376,6 +1390,7 @@ static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char *para char *p = skip_string(netname,1); int uLevel = SVAL(p,0); int snum = find_service(netname); + vuser_key key = { conn->smbd_pid, vuid }; if (snum < 0) return False; @@ -1385,7 +1400,7 @@ static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char *para *rdata = REALLOC(*rdata,mdrcnt); p = *rdata; - *rdata_len = fill_share_info(conn,vuid,snum,uLevel,&p,&mdrcnt,0,0,0); + *rdata_len = fill_share_info(conn,&key,snum,uLevel,&p,&mdrcnt,0,0,0); if (*rdata_len < 0) return False; *rparam_len = 6; @@ -1417,6 +1432,7 @@ static BOOL api_RNetShareEnum(connection_struct *conn,uint16 vuid, char *param,c int i; int data_len, fixed_len, string_len; int f_len = 0, s_len = 0; + vuser_key key = { conn->smbd_pid, vuid }; if (!prefix_ok(str1,"WrLeh")) return False; if (!check_share_info(uLevel,str2)) return False; @@ -1426,7 +1442,7 @@ static BOOL api_RNetShareEnum(connection_struct *conn,uint16 vuid, char *param,c if (lp_browseable(i) && lp_snum_ok(i)) { total++; - data_len += fill_share_info(conn,vuid,i,uLevel,0,&f_len,0,&s_len,0); + data_len += fill_share_info(conn,&key,i,uLevel,0,&f_len,0,&s_len,0); if (data_len <= buf_len) { counted++; @@ -1446,7 +1462,7 @@ static BOOL api_RNetShareEnum(connection_struct *conn,uint16 vuid, char *param,c s_len = string_len; for (i = 0; i < count;i++) if (lp_browseable(i) && lp_snum_ok(i)) - if (fill_share_info(conn,vuid,i,uLevel,&p,&f_len,&p2,&s_len,*rdata) < 0) + if (fill_share_info(conn,&key,i,uLevel,&p,&f_len,&p2,&s_len,*rdata) < 0) break; *rparam_len = 8; @@ -1659,6 +1675,7 @@ static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param char *p = skip_string(str2,1); int jobid, snum; int i, count; + vuser_key key = { conn->smbd_pid, vuid }; printjob_decode(SVAL(p,0), &snum, &jobid); @@ -1677,7 +1694,7 @@ static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param { print_queue_struct *queue=NULL; lpq_reset(snum); - count = get_printqueue(snum,conn,vuid,&queue,NULL); + count = get_printqueue(snum,conn,&key,&queue,NULL); for (i=0;i<count;i++) if ((queue[i].job&0xFF) == jobid) @@ -1685,13 +1702,13 @@ static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param switch (function) { case 81: /* delete */ DEBUG(3,("Deleting queue entry %d\n",queue[i].job)); - del_printqueue(conn,vuid,snum,queue[i].job); + del_printqueue(conn,&key,snum,queue[i].job); break; case 82: /* pause */ case 83: /* resume */ DEBUG(3,("%s queue entry %d\n", (function==82?"pausing":"resuming"),queue[i].job)); - status_printjob(conn,vuid,snum,queue[i].job, + status_printjob(conn,&key,snum,queue[i].job, (function==82?LPQ_PAUSED:LPQ_QUEUED)); break; } @@ -1722,6 +1739,7 @@ static BOOL api_WPrintQueuePurge(connection_struct *conn,uint16 vuid, char *para char *str2 = skip_string(str1,1); char *QueueName = skip_string(str2,1); int snum; + vuser_key key = { conn->smbd_pid, vuid }; /* check it's a supported varient */ if (!(strcsequal(str1,"z") && strcsequal(str2,""))) @@ -1750,17 +1768,19 @@ static BOOL api_WPrintQueuePurge(connection_struct *conn,uint16 vuid, char *para switch (function) { case 74: /* Pause queue */ case 75: /* Resume queue */ - status_printqueue(conn,vuid,snum,(function==74?LPSTAT_STOPPED:LPSTAT_OK)); + { + status_printqueue(conn,&key,snum,(function==74?LPSTAT_STOPPED:LPSTAT_OK)); DEBUG(3,("Print queue %s, queue=%s\n", (function==74?"pause":"resume"),QueueName)); break; + } case 103: /* Purge */ { print_queue_struct *queue=NULL; int i, count; - count = get_printqueue(snum,conn,vuid,&queue,NULL); + count = get_printqueue(snum,conn,&key,&queue,NULL); for (i = 0; i < count; i++) - del_printqueue(conn,vuid,snum,queue[i].job); + del_printqueue(conn,&key,snum,queue[i].job); if (queue) free(queue); DEBUG(3,("Print queue purge, queue=%s\n",QueueName)); @@ -1810,6 +1830,7 @@ static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,cha int i; char *s = data; files_struct *fsp; + vuser_key key = { conn->smbd_pid, vuid }; printjob_decode(SVAL(p,0), &snum, &jobid); @@ -1831,7 +1852,7 @@ static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,cha int count; lpq_reset(snum); - count = get_printqueue(snum,conn,vuid,&queue,NULL); + count = get_printqueue(snum,conn,&key,&queue,NULL); for (i=0;i<count;i++) /* find job */ if ((queue[i].job&0xFF) == jobid) break; @@ -1916,6 +1937,7 @@ static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *par int uLevel = SVAL(p,0); char *p2; int struct_len; + vuser_key key = { conn->smbd_pid, vuid }; DEBUG(4,("NetServerGetInfo level %d\n",uLevel)); @@ -1987,10 +2009,14 @@ static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *par if (mdrcnt == struct_len) { SIVAL(p,6,0); } else { + user_struct *vuser = get_valid_user_struct(&key); SIVAL(p,6,PTR_DIFF(p2,*rdata)); - standard_sub(conn,get_valid_user_struct(vuid), comment); + standard_sub(conn,vuser, comment); StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0)); p2 = skip_string(p2,1); + vuid_free_user_struct(vuser); + safe_free(vuser); + } } if (uLevel > 1) @@ -2261,11 +2287,12 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param char *p = skip_string(UserName,1); int uLevel = SVAL(p,0); char *p2; + vuser_key key = { conn->smbd_pid, vuid }; /* get NIS home of a previously validated user - simeon */ /* With share level security vuid will always be zero. Don't depend on vuser being non-null !!. JRA */ - user_struct *vuser = get_valid_user_struct(vuid); + user_struct *vuser = get_valid_user_struct(&key); if (vuser != NULL) DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid, vuser->name)); @@ -2283,10 +2310,20 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break; case 10: p2 = "B21Bzzz"; break; case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break; - default: return False; + default: + { + vuid_free_user_struct(vuser); + safe_free(vuser); + return False; + } } - if (strcmp(p2,str2) != 0) return False; + if (strcmp(p2,str2) != 0) + { + vuid_free_user_struct(vuser); + safe_free(vuser); + return False; + } *rdata_len = mdrcnt + 1024; *rdata = REALLOC(*rdata,*rdata_len); @@ -2327,7 +2364,7 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */ SIVALS(p,usri11_password_age,-1); /* password age */ SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */ - pstrcpy(p2, lp_logon_path(vuid)); + pstrcpy(p2, lp_logon_path(&key)); p2 = skip_string(p2,1); SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */ pstrcpy(p2,""); @@ -2363,7 +2400,7 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param SSVAL(p,42, conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER); SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */ - pstrcpy(p2,lp_logon_path(vuid)); + pstrcpy(p2,lp_logon_path(&key)); p2 = skip_string(p2,1); SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */ *p2++ = 0; @@ -2403,6 +2440,9 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param SSVAL(*rparam,4,*rdata_len); /* is this right?? */ + vuid_free_user_struct(vuser); + safe_free(vuser); + return(True); } @@ -2468,6 +2508,7 @@ static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param struct pack_desc desc; char* name; char* logon_script; + vuser_key key = { conn->smbd_pid, vuid }; uLevel = SVAL(p,0); name = p + 2; @@ -2487,6 +2528,7 @@ static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param if (init_package(&desc,1,0)) { + user_struct *vuser = get_valid_user_struct(&key); PACKI(&desc,"W",0); /* code */ PACKS(&desc,"B21",name); /* eff. name */ PACKS(&desc,"B",""); /* pad */ @@ -2513,8 +2555,10 @@ static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param /* JHT - By calling lp_logon_script() and standard_sub() we have */ /* made sure all macros are fully substituted and available */ - logon_script = lp_logon_script(vuid); - standard_sub( conn, get_valid_user_struct(vuid), logon_script ); + logon_script = lp_logon_script(&key); + standard_sub( conn, vuser, logon_script ); + vuid_free_user_struct(vuser); + safe_free(vuser); PACKS(&desc,"z", logon_script); /* script path */ /* End of JHT mods */ @@ -2580,6 +2624,7 @@ static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *para struct pack_desc desc; print_queue_struct *queue=NULL; print_status_struct status; + vuser_key key = { conn->smbd_pid, vuid }; uLevel = SVAL(p,2); @@ -2596,7 +2641,7 @@ static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *para if (snum < 0 || !VALID_SNUM(snum)) return(False); - count = get_printqueue(snum,conn,vuid,&queue,&status); + count = get_printqueue(snum,conn,&key,&queue,&status); for (i = 0; i < count; i++) { if ((queue[i].job & 0xFF) == job) break; } @@ -2643,6 +2688,7 @@ static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *pa struct pack_desc desc; print_queue_struct *queue=NULL; print_status_struct status; + vuser_key key = { conn->smbd_pid, vuid }; bzero(&desc,sizeof(desc)); bzero(&status,sizeof(status)); @@ -2668,7 +2714,7 @@ static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *pa if (snum < 0 || !VALID_SNUM(snum)) return(False); - count = get_printqueue(snum,conn,vuid,&queue,&status); + count = get_printqueue(snum,conn,&key,&queue,&status); if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); desc.base = *rdata; desc.buflen = mdrcnt; diff --git a/source/smbd/open.c b/source/smbd/open.c index fe20d95ef8b..7608a25d80f 100644 --- a/source/smbd/open.c +++ b/source/smbd/open.c @@ -501,7 +501,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, conn->num_files_open++; fsp->mode = sbuf->st_mode; GetTimeOfDay(&fsp->open_time); - fsp->vuid = current_user.vuid; + fsp->vuid = current_user.key.vuid; fsp->size = 0; fsp->pos = -1; fsp->open = True; @@ -1063,7 +1063,7 @@ int open_directory(files_struct *fsp,connection_struct *conn, conn->num_files_open++; fsp->mode = 0; GetTimeOfDay(&fsp->open_time); - fsp->vuid = current_user.vuid; + fsp->vuid = current_user.key.vuid; fsp->size = 0; fsp->pos = -1; fsp->open = True; diff --git a/source/smbd/oplock.c b/source/smbd/oplock.c index 99fe7a69fab..1850c8c9d9a 100644 --- a/source/smbd/oplock.c +++ b/source/smbd/oplock.c @@ -697,7 +697,7 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval) * user, then unbecome the user whilst we're doing this. */ saved_conn = fsp->conn; - saved_vuid = current_user.vuid; + saved_vuid = current_user.key.vuid; dos_GetWd(saved_dir); unbecome_user(); /* Save the chain fnum. */ diff --git a/source/smbd/password.c b/source/smbd/password.c index 2141525bc09..005e36c9b85 100644 --- a/source/smbd/password.c +++ b/source/smbd/password.c @@ -192,16 +192,18 @@ static char *validate_group(char *group,char *password,int pwlen,int snum, /**************************************************************************** check for authority to login to a service with a given username/password ****************************************************************************/ -BOOL authorise_login(int snum,char *user, char *domain, +BOOL authorise_login(int snum, char *user, char *domain, char *password, int pwlen, - BOOL *guest,BOOL *force,uint16 vuid) + BOOL *guest,BOOL *force, + const vuser_key *key) { - BOOL ok = False; - - *guest = False; - + BOOL ok = False; + + DEBUG(0,("authorise_login: TODO. split function, it's 6 levels!\n")); + *guest = False; + #if DEBUG_PASSWORD - DEBUG(100,("checking authorisation on user=%s pass=%s\n",user,password)); + DEBUG(100,("checking authorisation on user=%s pass=%s\n",user,password)); #endif /* there are several possibilities: @@ -216,136 +218,154 @@ BOOL authorise_login(int snum,char *user, char *domain, if the service is guest_only then steps 1 to 5 are skipped */ - if (GUEST_ONLY(snum)) *force = True; - - if (!(GUEST_ONLY(snum) && GUEST_OK(snum))) - { + if (GUEST_ONLY(snum)) *force = True; - user_struct *vuser = get_valid_user_struct(vuid); - - /* check the given username and password */ - if (!ok && (*user) && user_ok(user,snum)) { - ok = password_ok(user,domain, password, pwlen, NULL, 0, NULL, &vuser->usr); - if (ok) DEBUG(3,("ACCEPTED: given username password ok\n")); - } + if (!(GUEST_ONLY(snum) && GUEST_OK(snum))) + { + user_struct *vuser = get_valid_user_struct(key); - /* check for a previously registered guest username */ - if (!ok && (vuser != 0) && vuser->guest) { - if (user_ok(vuser->name,snum) && - password_ok(vuser->name, domain, password, pwlen, NULL, 0, NULL, &vuser->usr)) { - fstrcpy(user, vuser->name); - vuser->guest = False; - DEBUG(3,("ACCEPTED: given password with registered user %s\n", user)); - ok = True; - } - } + /* check the given username and password */ + if (!ok && (*user) && user_ok(user,snum)) + { + ok = password_ok(user,domain, password, pwlen, NULL, 0, NULL, &vuser->usr); + if (ok) DEBUG(3,("ACCEPTED: given username password ok\n")); + } + /* check for a previously registered guest username */ + if (!ok && (vuser != 0) && vuser->guest) + { + if (user_ok(vuser->name,snum) && + password_ok(vuser->name, domain, password, pwlen, NULL, 0, NULL, &vuser->usr)) + { + fstrcpy(user, vuser->name); + vuser->guest = False; + DEBUG(3,("ACCEPTED: given password with registered user %s\n", user)); + ok = True; + } + } - /* now check the list of session users */ - if (!ok) - { - char *auser; - char *user_list = strdup(session_users); - if (!user_list) return False; - for (auser=strtok(user_list,LIST_SEP); - !ok && auser; - auser = strtok(NULL,LIST_SEP)) - { - fstring user2; - fstrcpy(user2,auser); - if (!user_ok(user2,snum)) continue; - - if (password_ok(user2, domain, password, pwlen, NULL, 0, NULL, - &vuser->usr)) - { - ok = True; - fstrcpy(user,user2); - DEBUG(3,("ACCEPTED: session list username and given password ok\n")); - } - } - free(user_list); - } + /* now check the list of session users */ + if (!ok) + { + char *auser; + char *user_list = strdup(session_users); + if (!user_list) + { + vuid_free_user_struct(vuser); + safe_free(vuser); + return False; + } + + for (auser=strtok(user_list,LIST_SEP); + !ok && auser; + auser = strtok(NULL,LIST_SEP)) + { + fstring user2; + fstrcpy(user2,auser); + if (!user_ok(user2,snum)) continue; + + if (password_ok(user2, domain, password, pwlen, NULL, 0, NULL, + &vuser->usr)) + { + ok = True; + fstrcpy(user,user2); + DEBUG(3,("ACCEPTED: session list username and given password ok\n")); + } + } + free(user_list); + } - /* check for a previously validated username/password pair */ - if (!ok && (!lp_revalidate(snum) || lp_security() > SEC_SHARE) && - (vuser != 0) && !vuser->guest && - user_ok(vuser->name,snum)) { - fstrcpy(user,vuser->name); - *guest = False; - DEBUG(3,("ACCEPTED: validated uid ok as non-guest\n")); - ok = True; - } + /* check for a previously validated username/password pair */ + if (!ok && (!lp_revalidate(snum) || lp_security() > SEC_SHARE) && + (vuser != 0) && !vuser->guest && + user_ok(vuser->name,snum)) + { + fstrcpy(user,vuser->name); + *guest = False; + DEBUG(3,("ACCEPTED: validated uid ok as non-guest\n")); + ok = True; + } - /* check for a rhosts entry */ - if (!ok && user_ok(user,snum) && check_hosts_equiv(user)) { - ok = True; - DEBUG(3,("ACCEPTED: hosts equiv or rhosts entry\n")); - } + /* check for a rhosts entry */ + if (!ok && user_ok(user,snum) && check_hosts_equiv(user)) + { + ok = True; + DEBUG(3,("ACCEPTED: hosts equiv or rhosts entry\n")); + } - /* check the user= fields and the given password */ - if (!ok && lp_username(snum)) { - char *auser; - pstring user_list; - StrnCpy(user_list,lp_username(snum),sizeof(pstring)); + /* check the user= fields and the given password */ + if (!ok && lp_username(snum)) + { + char *auser; + pstring user_list; + StrnCpy(user_list,lp_username(snum),sizeof(pstring)); + + string_sub(user_list,"%S",lp_servicename(snum)); + + for (auser=strtok(user_list,LIST_SEP); + auser && !ok; + auser = strtok(NULL,LIST_SEP)) + { + if (*auser == '@') + { + auser = validate_group(auser+1,password,pwlen,snum, &vuser->usr); + if (auser) + { + ok = True; + fstrcpy(user,auser); + DEBUG(3,("ACCEPTED: group username and given password ok\n")); + } + } + else + { + fstring user2; + fstrcpy(user2,auser); + if (user_ok(user2,snum) && + password_ok(user2,domain,password,pwlen,NULL, 0, + NULL, &vuser->usr)) + { + ok = True; + fstrcpy(user,user2); + DEBUG(3,("ACCEPTED: user list username and given password ok\n")); + } + } + } + } + + if (vuser != NULL) + { + tdb_store_vuid(key, vuser); + } + vuid_free_user_struct(vuser); + safe_free(vuser); - string_sub(user_list,"%S",lp_servicename(snum)); - - for (auser=strtok(user_list,LIST_SEP); - auser && !ok; - auser = strtok(NULL,LIST_SEP)) - { - if (*auser == '@') - { - auser = validate_group(auser+1,password,pwlen,snum, &vuser->usr); - if (auser) - { - ok = True; - fstrcpy(user,auser); - DEBUG(3,("ACCEPTED: group username and given password ok\n")); - } - } - else - { - fstring user2; - fstrcpy(user2,auser); - if (user_ok(user2,snum) && - password_ok(user2,domain,password,pwlen,NULL, 0, - NULL, &vuser->usr)) - { - ok = True; - fstrcpy(user,user2); - DEBUG(3,("ACCEPTED: user list username and given password ok\n")); - } - } - } - } - } /* not guest only */ + } /* not guest only */ - /* check for a normal guest connection */ - if (!ok && GUEST_OK(snum)) - { - fstring guestname; - StrnCpy(guestname,lp_guestaccount(snum),sizeof(guestname)-1); - if (Get_Pwnam(guestname,True)) + /* check for a normal guest connection */ + if (!ok && GUEST_OK(snum)) { - fstrcpy(user,guestname); - ok = True; - DEBUG(3,("ACCEPTED: guest account and guest ok\n")); + fstring guestname; + StrnCpy(guestname,lp_guestaccount(snum),sizeof(guestname)-1); + if (Get_Pwnam(guestname,True)) + { + fstrcpy(user,guestname); + ok = True; + DEBUG(3,("ACCEPTED: guest account and guest ok\n")); + } + else + DEBUG(0,("Invalid guest account %s??\n",guestname)); + *guest = True; + *force = True; } - else - DEBUG(0,("Invalid guest account %s??\n",guestname)); - *guest = True; - *force = True; - } - if (ok && !user_ok(user,snum)) - { - DEBUG(0,("rejected invalid user %s\n",user)); - ok = False; - } + if (ok && !user_ok(user,snum)) + { + DEBUG(0,("rejected invalid user %s\n",user)); + ok = False; + } - return(ok); + return(ok); } diff --git a/source/smbd/process.c b/source/smbd/process.c index d391914f600..e95135a484a 100644 --- a/source/smbd/process.c +++ b/source/smbd/process.c @@ -435,14 +435,20 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize * move it unless you know what you're doing... :-). * JRA. */ - if (session_tag != last_session_tag) { + if (session_tag != last_session_tag) + { user_struct *vuser = NULL; + vuser_key key = { pid, session_tag }; last_session_tag = session_tag; if(session_tag != UID_FIELD_INVALID) - vuser = get_valid_user_struct(session_tag); + vuser = get_valid_user_struct(&key); if(vuser != NULL) + { pstrcpy( sesssetup_user, vuser->requested_name); + vuid_free_user_struct(vuser); + safe_free(vuser); + } } /* does this protocol need to be run as root? */ diff --git a/source/smbd/reply.c b/source/smbd/reply.c index cee776351a6..51842b9462f 100644 --- a/source/smbd/reply.c +++ b/source/smbd/reply.c @@ -384,6 +384,7 @@ static int session_trust_account(connection_struct *conn, if (last_challenge(last_chal)) { NET_USER_INFO_3 info3; + ZERO_STRUCT(info3); status = check_domain_security(user, domain, last_chal, (uchar *)smb_passwd, smb_passlen, @@ -426,6 +427,8 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int BOOL doencrypt = SMBENCRYPT(); char *domain = ""; + ZERO_STRUCT(info3); + *smb_apasswd = 0; *smb_ntpasswd = 0; @@ -693,7 +696,7 @@ user %s attempted down-level SMB connection\n", user)); /* register the name and uid as being validated, so further connections to a uid can get through without a password, on the same VC */ - sess_vuid = register_vuid(uid,gid,user,sesssetup_user,guest,&info3); + sess_vuid = register_vuid(getpid(), uid,gid,user,sesssetup_user,guest,&info3); SSVAL(outbuf,smb_uid,sess_vuid); SSVAL(inbuf,smb_uid,sess_vuid); @@ -1450,9 +1453,14 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) { uint16 vuid = SVAL(inbuf,smb_uid); - user_struct *vuser = get_valid_user_struct(vuid); + vuser_key key; + user_struct *vuser = NULL; + key.pid = conn != NULL ? conn->smbd_pid : getpid(); + key.vuid = vuid; + vuser = get_valid_user_struct(&key); - if(vuser == 0) { + if (vuser == 0) + { DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid)); } @@ -1462,7 +1470,7 @@ int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length, file_close_user(vuid); } - invalidate_vuid(vuid); + invalidate_vuid(&key); set_message(outbuf,2,0,True); @@ -2764,6 +2772,7 @@ int reply_printqueue(connection_struct *conn, int max_count = SVAL(inbuf,smb_vwv0); int start_index = SVAL(inbuf,smb_vwv1); uint16 vuid = SVAL(inbuf,smb_uid); + vuser_key key = { conn->smbd_pid, vuid }; /* we used to allow the client to get the cnum wrong, but that is really quite gross and only worked when there was only @@ -2783,7 +2792,7 @@ int reply_printqueue(connection_struct *conn, { print_queue_struct *queue = NULL; char *p = smb_buf(outbuf) + 3; - int count = get_printqueue(SNUM(conn), conn, vuid, &queue,NULL); + int count = get_printqueue(SNUM(conn), conn, &key, &queue,NULL); int num_to_get = ABS(max_count); int first = (max_count>0?start_index:start_index+max_count+1); int i; diff --git a/source/smbd/service.c b/source/smbd/service.c index 8a0ba725b09..a251cfcfa63 100644 --- a/source/smbd/service.c +++ b/source/smbd/service.c @@ -202,6 +202,10 @@ connection_struct *make_connection(char *service,char *user, BOOL force = False; extern int Client; connection_struct *conn; + vuser_key key; + + key.pid = getpid(); + key.vuid = vuid; strlower(service); @@ -224,9 +228,12 @@ connection_struct *make_connection(char *service,char *user, return(make_connection(user,user,domain,password, pwlen,dev,vuid,ecode)); - if(lp_security() != SEC_SHARE) { - if (validated_username(vuid)) { - pstrcpy(user,validated_username(vuid)); + if(lp_security() != SEC_SHARE) + { + fstring user_name; + if (validated_username(&key, user_name, sizeof(user_name))) + { + pstrcpy(user, user_name); return(make_connection(user,user,domain,password,pwlen,dev,vuid,ecode)); } } else { @@ -273,7 +280,7 @@ connection_struct *make_connection(char *service,char *user, add_session_user(service); /* shall we let them in? */ - if (!authorise_login(snum,user,domain,password,pwlen,&guest,&force,vuid)) + if (!authorise_login(snum,user,domain,password,pwlen,&guest,&force,&key)) { DEBUG( 2, ( "Invalid username/password for %s\n", service ) ); *ecode = ERRbadpw; @@ -411,8 +418,11 @@ connection_struct *make_connection(char *service,char *user, { pstring s; + user_struct *vuser = get_valid_user_struct(&key); pstrcpy(s,lp_pathname(snum)); - standard_sub(conn,get_valid_user_struct(vuid), s); + standard_sub(conn,vuser, s); + vuid_free_user_struct(vuser); + safe_free(vuser); string_set(&conn->connectpath,s); DEBUG(3,("Connect path is %s\n",s)); } @@ -444,10 +454,14 @@ connection_struct *make_connection(char *service,char *user, } /* IS_IPC */ /* execute any "root preexec = " line */ - if (*lp_rootpreexec(SNUM(conn))) { + if (*lp_rootpreexec(SNUM(conn))) + { pstring cmd; + user_struct *vuser = get_valid_user_struct(&key); pstrcpy(cmd,lp_rootpreexec(SNUM(conn))); - standard_sub(conn,get_valid_user_struct(vuid), cmd); + standard_sub(conn,vuser, cmd); + vuid_free_user_struct(vuser); + safe_free(vuser); DEBUG(5,("cmd=%s\n",cmd)); smbrun(cmd,NULL,False); } @@ -499,10 +513,14 @@ connection_struct *make_connection(char *service,char *user, add_session_user(user); /* execute any "preexec = " line */ - if (*lp_preexec(SNUM(conn))) { + if (*lp_preexec(SNUM(conn))) + { pstring cmd; + user_struct *vuser = get_valid_user_struct(&key); pstrcpy(cmd,lp_preexec(SNUM(conn))); - standard_sub(conn,get_valid_user_struct(vuid), cmd); + standard_sub(conn,vuser, cmd); + vuid_free_user_struct(vuser); + safe_free(vuser); smbrun(cmd,NULL,False); } @@ -522,7 +540,7 @@ connection_struct *make_connection(char *service,char *user, dbgtext( "connect to service %s ", lp_servicename(SNUM(conn))); dbgtext( "as user %s ", user ); dbgtext( "(uid=%d, gid=%d) ", (int)conn->uid, (int)conn->gid ); - dbgtext( "(pid %d)\n", (int)getpid() ); + dbgtext( "(pid %d)\n", (int)key.pid ); } /* Invoke make connection hook */ @@ -576,6 +594,8 @@ close a cnum ****************************************************************************/ void close_cnum(connection_struct *conn, uint16 vuid) { + vuser_key key = { conn->smbd_pid, vuid }; + DirCacheFlush(SNUM(conn)); unbecome_user(); @@ -612,20 +632,28 @@ void close_cnum(connection_struct *conn, uint16 vuid) /* execute any "postexec = " line */ if (*lp_postexec(SNUM(conn)) && - become_user(conn, vuid)) { + become_user(conn, vuid)) + { + user_struct *vuser = get_valid_user_struct(&key); pstring cmd; pstrcpy(cmd,lp_postexec(SNUM(conn))); - standard_sub(conn,get_valid_user_struct(vuid), cmd); + standard_sub(conn,vuser, cmd); + vuid_free_user_struct(vuser); + safe_free(vuser); smbrun(cmd,NULL,False); unbecome_user(); } unbecome_user(); /* execute any "root postexec = " line */ - if (*lp_rootpostexec(SNUM(conn))) { + if (*lp_rootpostexec(SNUM(conn))) + { + user_struct *vuser = get_valid_user_struct(&key); pstring cmd; pstrcpy(cmd,lp_rootpostexec(SNUM(conn))); - standard_sub(conn,get_valid_user_struct(vuid), cmd); + standard_sub(conn,vuser, cmd); + vuid_free_user_struct(vuser); + safe_free(vuser); smbrun(cmd,NULL,False); } diff --git a/source/smbd/uid.c b/source/smbd/uid.c index bbaf73eef06..6b05cfda2f4 100644 --- a/source/smbd/uid.c +++ b/source/smbd/uid.c @@ -30,7 +30,17 @@ extern struct current_user current_user; ****************************************************************************/ BOOL become_user(connection_struct *conn, uint16 vuid) { - user_struct *vuser = get_valid_user_struct(vuid); + vuser_key key; + key.pid = getpid(); + key.vuid = vuid; + return become_userk(conn, &key); +} +/**************************************************************************** + Become the user of a connection number. +****************************************************************************/ +BOOL become_userk(connection_struct *conn, const vuser_key *key) +{ + user_struct *vuser = NULL; int snum; gid_t gid = -1; uid_t uid = -1; @@ -55,13 +65,21 @@ BOOL become_user(connection_struct *conn, uint16 vuid) (current_user.uid == conn->uid)) { DEBUG(4,("Skipping become_user - already user\n")); + return(True); } - else if ((current_user.conn == conn) && - (vuser != NULL) && (current_user.vuid == vuid) && + + vuser = get_valid_user_struct(key); + + if ((current_user.conn == conn) && + (vuser != NULL) && + (current_user.key.vuid == key->vuid) && + (current_user.key.pid == key->pid) && (current_user.uid == vuser->uid)) { DEBUG(4,("Skipping become_user - already user\n")); + vuid_free_user_struct(vuser); + safe_free(vuser); return(True); } @@ -70,7 +88,11 @@ BOOL become_user(connection_struct *conn, uint16 vuid) snum = SNUM(conn); if((vuser != NULL) && !check_vuser_ok(&conn->uid_cache, vuser, snum)) + { + vuid_free_user_struct(vuser); + safe_free(vuser); return False; + } if (conn->force_user || lp_security() == SEC_SHARE || @@ -81,7 +103,7 @@ BOOL become_user(connection_struct *conn, uint16 vuid) ngroups = conn->ngroups; } else { if (!vuser) { - DEBUG(2,("Invalid vuid used %d\n",vuid)); + DEBUG(2,("Invalid vuid used %d\n",key->vuid)); return(False); } uid = vuser->uid; @@ -118,7 +140,10 @@ BOOL become_user(connection_struct *conn, uint16 vuid) } } - return become_unix_sec_ctx(vuid, conn, uid, gid, ngroups, groups); + vuid_free_user_struct(vuser); + safe_free(vuser); + + return become_unix_sec_ctx(key, conn, uid, gid, ngroups, groups); } /**************************************************************************** |