static BOOL canonicalize_path | ( | connection_struct * | conn, | |
pstring | path | |||
) | [static] |
00026 { 00027 #ifdef REALPATH_TAKES_NULL 00028 char *resolved_name = SMB_VFS_REALPATH(conn,path,NULL); 00029 if (!resolved_name) { 00030 return False; 00031 } 00032 pstrcpy(path, resolved_name); 00033 SAFE_FREE(resolved_name); 00034 return True; 00035 #else 00036 #ifdef PATH_MAX 00037 char resolved_name_buf[PATH_MAX+1]; 00038 #else 00039 pstring resolved_name_buf; 00040 #endif 00041 char *resolved_name = SMB_VFS_REALPATH(conn,path,resolved_name_buf); 00042 if (!resolved_name) { 00043 return False; 00044 } 00045 pstrcpy(path, resolved_name); 00046 return True; 00047 #endif /* REALPATH_TAKES_NULL */ 00048 }
void set_conn_connectpath | ( | connection_struct * | conn, | |
const pstring | connectpath | |||
) |
参照先 connection_struct::connectpath・next_codepoint()・string_set().
参照元 create_conn_struct()・get_nt_acl_no_snum()・reply_setdir().
00057 { 00058 pstring destname; 00059 char *d = destname; 00060 const char *s = connectpath; 00061 BOOL start_of_name_component = True; 00062 00063 *d++ = '/'; /* Always start with root. */ 00064 00065 while (*s) { 00066 if (*s == '/') { 00067 /* Eat multiple '/' */ 00068 while (*s == '/') { 00069 s++; 00070 } 00071 if ((d > destname + 1) && (*s != '\0')) { 00072 *d++ = '/'; 00073 } 00074 start_of_name_component = True; 00075 continue; 00076 } 00077 00078 if (start_of_name_component) { 00079 if ((s[0] == '.') && (s[1] == '.') && (s[2] == '/' || s[2] == '\0')) { 00080 /* Uh oh - "/../" or "/..\0" ! */ 00081 00082 /* Go past the ../ or .. */ 00083 if (s[2] == '/') { 00084 s += 3; 00085 } else { 00086 s += 2; /* Go past the .. */ 00087 } 00088 00089 /* If we just added a '/' - delete it */ 00090 if ((d > destname) && (*(d-1) == '/')) { 00091 *(d-1) = '\0'; 00092 d--; 00093 } 00094 00095 /* Are we at the start ? Can't go back further if so. */ 00096 if (d <= destname) { 00097 *d++ = '/'; /* Can't delete root */ 00098 continue; 00099 } 00100 /* Go back one level... */ 00101 /* Decrement d first as d points to the *next* char to write into. */ 00102 for (d--; d > destname; d--) { 00103 if (*d == '/') { 00104 break; 00105 } 00106 } 00107 /* We're still at the start of a name component, just the previous one. */ 00108 continue; 00109 } else if ((s[0] == '.') && ((s[1] == '\0') || s[1] == '/')) { 00110 /* Component of pathname can't be "." only - skip the '.' . */ 00111 if (s[1] == '/') { 00112 s += 2; 00113 } else { 00114 s++; 00115 } 00116 continue; 00117 } 00118 } 00119 00120 if (!(*s & 0x80)) { 00121 *d++ = *s++; 00122 } else { 00123 size_t siz; 00124 /* Get the size of the next MB character. */ 00125 next_codepoint(s,&siz); 00126 switch(siz) { 00127 case 5: 00128 *d++ = *s++; 00129 /*fall through*/ 00130 case 4: 00131 *d++ = *s++; 00132 /*fall through*/ 00133 case 3: 00134 *d++ = *s++; 00135 /*fall through*/ 00136 case 2: 00137 *d++ = *s++; 00138 /*fall through*/ 00139 case 1: 00140 *d++ = *s++; 00141 break; 00142 default: 00143 break; 00144 } 00145 } 00146 start_of_name_component = False; 00147 } 00148 *d = '\0'; 00149 00150 /* And must not end in '/' */ 00151 if (d > destname + 1 && (*(d-1) == '/')) { 00152 *(d-1) = '\0'; 00153 } 00154 00155 DEBUG(10,("set_conn_connectpath: service %s, connectpath = %s\n", 00156 lp_servicename(SNUM(conn)), destname )); 00157 00158 string_set(&conn->connectpath, destname); 00159 }
BOOL set_current_service | ( | connection_struct * | conn, | |
uint16 | flags, | |||
BOOL | do_chdir | |||
) |
参照先 connection_struct::case_sensitive・connection_struct::connectpath・get_remote_arch()・connection_struct::lastused_count・connection_struct::origpath・RA_CIFSFS・RA_SAMBA・ra_type・vfs_ChDir().
参照元 conn_close_all()・process_blocking_lock_queue()・reload_services()・switch_message().
00166 { 00167 static connection_struct *last_conn; 00168 static uint16 last_flags; 00169 int snum; 00170 00171 if (!conn) { 00172 last_conn = NULL; 00173 return(False); 00174 } 00175 00176 conn->lastused_count++; 00177 00178 snum = SNUM(conn); 00179 00180 if (do_chdir && 00181 vfs_ChDir(conn,conn->connectpath) != 0 && 00182 vfs_ChDir(conn,conn->origpath) != 0) { 00183 DEBUG(0,("chdir (%s) failed\n", 00184 conn->connectpath)); 00185 return(False); 00186 } 00187 00188 if ((conn == last_conn) && (last_flags == flags)) { 00189 return(True); 00190 } 00191 00192 last_conn = conn; 00193 last_flags = flags; 00194 00195 /* Obey the client case sensitivity requests - only for clients that support it. */ 00196 switch (lp_casesensitive(snum)) { 00197 case Auto: 00198 { 00199 /* We need this uglyness due to DOS/Win9x clients that lie about case insensitivity. */ 00200 enum remote_arch_types ra_type = get_remote_arch(); 00201 if ((ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) { 00202 /* Client can't support per-packet case sensitive pathnames. */ 00203 conn->case_sensitive = False; 00204 } else { 00205 conn->case_sensitive = !(flags & FLAG_CASELESS_PATHNAMES); 00206 } 00207 } 00208 break; 00209 case True: 00210 conn->case_sensitive = True; 00211 break; 00212 default: 00213 conn->case_sensitive = False; 00214 break; 00215 } 00216 return(True); 00217 }
int add_home_service | ( | const char * | service, | |
const char * | username, | |||
const char * | homedir | |||
) |
参照先 lp_add_home().
参照元 find_service()・register_vuid().
00224 { 00225 int iHomeService; 00226 00227 if (!service || !homedir) 00228 return -1; 00229 00230 if ((iHomeService = lp_servicenumber(HOMES_NAME)) < 0) 00231 return -1; 00232 00233 /* 00234 * If this is a winbindd provided username, remove 00235 * the domain component before adding the service. 00236 * Log a warning if the "path=" parameter does not 00237 * include any macros. 00238 */ 00239 00240 { 00241 const char *p = strchr(service,*lp_winbind_separator()); 00242 00243 /* We only want the 'user' part of the string */ 00244 if (p) { 00245 service = p + 1; 00246 } 00247 } 00248 00249 if (!lp_add_home(service, iHomeService, username, homedir)) { 00250 return -1; 00251 } 00252 00253 return lp_servicenumber(service); 00254 00255 }
int find_service | ( | fstring | service | ) |
Find a service entry.
service | is modified (to canonical form??) |
参照先 add_home_service()・all_string_sub()・find_service()・get_user_home_dir()・load_usershare_service()・lp_add_printer()・lp_add_service()・map_username()・pcap_printername_ok()・strequal()・strlower_m()・strstr_m().
00265 { 00266 int iService; 00267 00268 all_string_sub(service,"\\","/",0); 00269 00270 iService = lp_servicenumber(service); 00271 00272 /* now handle the special case of a home directory */ 00273 if (iService < 0) { 00274 char *phome_dir = get_user_home_dir(service); 00275 00276 if(!phome_dir) { 00277 /* 00278 * Try mapping the servicename, it may 00279 * be a Windows to unix mapped user name. 00280 */ 00281 if(map_username(service)) 00282 phome_dir = get_user_home_dir(service); 00283 } 00284 00285 DEBUG(3,("checking for home directory %s gave %s\n",service, 00286 phome_dir?phome_dir:"(NULL)")); 00287 00288 iService = add_home_service(service,service /* 'username' */, phome_dir); 00289 } 00290 00291 /* If we still don't have a service, attempt to add it as a printer. */ 00292 if (iService < 0) { 00293 int iPrinterService; 00294 00295 if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) >= 0) { 00296 DEBUG(3,("checking whether %s is a valid printer name...\n", service)); 00297 if (pcap_printername_ok(service)) { 00298 DEBUG(3,("%s is a valid printer name\n", service)); 00299 DEBUG(3,("adding %s as a printer service\n", service)); 00300 lp_add_printer(service, iPrinterService); 00301 iService = lp_servicenumber(service); 00302 if (iService < 0) { 00303 DEBUG(0,("failed to add %s as a printer service!\n", service)); 00304 } 00305 } else { 00306 DEBUG(3,("%s is not a valid printer name\n", service)); 00307 } 00308 } 00309 } 00310 00311 /* Check for default vfs service? Unsure whether to implement this */ 00312 if (iService < 0) { 00313 } 00314 00315 /* Is it a usershare service ? */ 00316 if (iService < 0 && *lp_usershare_path()) { 00317 /* Ensure the name is canonicalized. */ 00318 strlower_m(service); 00319 iService = load_usershare_service(service); 00320 } 00321 00322 /* just possibly it's a default service? */ 00323 if (iService < 0) { 00324 char *pdefservice = lp_defaultservice(); 00325 if (pdefservice && *pdefservice && !strequal(pdefservice,service) && !strstr_m(service,"..")) { 00326 /* 00327 * We need to do a local copy here as lp_defaultservice() 00328 * returns one of the rotating lp_string buffers that 00329 * could get overwritten by the recursive find_service() call 00330 * below. Fix from Josef Hinteregger <joehtg@joehtg.co.at>. 00331 */ 00332 pstring defservice; 00333 pstrcpy(defservice, pdefservice); 00334 00335 /* Disallow anything except explicit share names. */ 00336 if (strequal(defservice,HOMES_NAME) || 00337 strequal(defservice, PRINTERS_NAME) || 00338 strequal(defservice, "IPC$")) { 00339 goto fail; 00340 } 00341 00342 iService = find_service(defservice); 00343 if (iService >= 0) { 00344 all_string_sub(service, "_","/",0); 00345 iService = lp_add_service(service, iService); 00346 } 00347 } 00348 } 00349 00350 if (iService >= 0) { 00351 if (!VALID_SNUM(iService)) { 00352 DEBUG(0,("Invalid snum %d for %s\n",iService, service)); 00353 iService = -1; 00354 } 00355 } 00356 00357 fail: 00358 00359 if (iService < 0) 00360 DEBUG(3,("find_service() failed to find service %s\n", service)); 00361 00362 return (iService); 00363 }
参照先 check_access()・lp_snum_ok()・smbd_server_fd()・strequal()・strupper_m().
00372 { 00373 00374 if (!lp_snum_ok(snum) || 00375 !check_access(smbd_server_fd(), 00376 lp_hostsallow(snum), lp_hostsdeny(snum))) { 00377 return NT_STATUS_ACCESS_DENIED; 00378 } 00379 00380 if (dev[0] == '?' || !dev[0]) { 00381 if (lp_print_ok(snum)) { 00382 fstrcpy(dev,"LPT1:"); 00383 } else if (strequal(lp_fstype(snum), "IPC")) { 00384 fstrcpy(dev, "IPC"); 00385 } else { 00386 fstrcpy(dev,"A:"); 00387 } 00388 } 00389 00390 strupper_m(dev); 00391 00392 if (lp_print_ok(snum)) { 00393 if (!strequal(dev, "LPT1:")) { 00394 return NT_STATUS_BAD_DEVICE_TYPE; 00395 } 00396 } else if (strequal(lp_fstype(snum), "IPC")) { 00397 if (!strequal(dev, "IPC")) { 00398 return NT_STATUS_BAD_DEVICE_TYPE; 00399 } 00400 } else if (!strequal(dev, "A:")) { 00401 return NT_STATUS_BAD_DEVICE_TYPE; 00402 } 00403 00404 /* Behave as a printer if we are supposed to */ 00405 if (lp_print_ok(snum) && (strcmp(dev, "A:") == 0)) { 00406 fstrcpy(dev, "LPT1:"); 00407 } 00408 00409 return NT_STATUS_OK; 00410 }
static NTSTATUS find_forced_user | ( | connection_struct * | conn, | |
BOOL | vuser_is_guest, | |||
fstring | username | |||
) | [static] |
参照先 create_token_from_username()・connection_struct::gid・connection_struct::mem_ctx・connection_struct::nt_user_token・connection_struct::params・result・share_params::service・talloc_string_sub()・connection_struct::uid.
00413 { 00414 int snum = conn->params->service; 00415 char *fuser, *found_username; 00416 NTSTATUS result; 00417 00418 if (!(fuser = talloc_string_sub(conn->mem_ctx, lp_force_user(snum), "%S", 00419 lp_servicename(snum)))) { 00420 return NT_STATUS_NO_MEMORY; 00421 } 00422 00423 result = create_token_from_username(conn->mem_ctx, fuser, vuser_is_guest, 00424 &conn->uid, &conn->gid, &found_username, 00425 &conn->nt_user_token); 00426 if (!NT_STATUS_IS_OK(result)) { 00427 return result; 00428 } 00429 00430 fstrcpy(username, found_username); 00431 00432 TALLOC_FREE(fuser); 00433 TALLOC_FREE(found_username); 00434 return NT_STATUS_OK; 00435 }
static NTSTATUS find_forced_group | ( | BOOL | force_user, | |
int | snum, | |||
const char * | username, | |||
DOM_SID * | pgroup_sid, | |||
gid_t * | pgid | |||
) | [static] |
参照先 lookup_name_smbconf()・result・sid_copy()・SID_NAME_ALIAS・SID_NAME_DOM_GRP・SID_NAME_WKN_GRP・sid_string_static()・sid_to_gid()・sid_type_lookup()・talloc_strdup()・talloc_string_sub()・type・user_in_group_sid().
00448 { 00449 NTSTATUS result = NT_STATUS_NO_SUCH_GROUP; 00450 TALLOC_CTX *mem_ctx; 00451 DOM_SID group_sid; 00452 enum lsa_SidType type; 00453 char *groupname; 00454 BOOL user_must_be_member = False; 00455 gid_t gid; 00456 00457 ZERO_STRUCTP(pgroup_sid); 00458 *pgid = (gid_t)-1; 00459 00460 mem_ctx = talloc_new(NULL); 00461 if (mem_ctx == NULL) { 00462 DEBUG(0, ("talloc_new failed\n")); 00463 return NT_STATUS_NO_MEMORY; 00464 } 00465 00466 groupname = talloc_strdup(mem_ctx, lp_force_group(snum)); 00467 if (groupname == NULL) { 00468 DEBUG(1, ("talloc_strdup failed\n")); 00469 result = NT_STATUS_NO_MEMORY; 00470 goto done; 00471 } 00472 00473 if (groupname[0] == '+') { 00474 user_must_be_member = True; 00475 groupname += 1; 00476 } 00477 00478 groupname = talloc_string_sub(mem_ctx, groupname, 00479 "%S", lp_servicename(snum)); 00480 00481 if (!lookup_name_smbconf(mem_ctx, groupname, 00482 LOOKUP_NAME_ALL|LOOKUP_NAME_GROUP, 00483 NULL, NULL, &group_sid, &type)) { 00484 DEBUG(10, ("lookup_name_smbconf(%s) failed\n", 00485 groupname)); 00486 goto done; 00487 } 00488 00489 if ((type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) && 00490 (type != SID_NAME_WKN_GRP)) { 00491 DEBUG(10, ("%s is a %s, not a group\n", groupname, 00492 sid_type_lookup(type))); 00493 goto done; 00494 } 00495 00496 if (!sid_to_gid(&group_sid, &gid)) { 00497 DEBUG(10, ("sid_to_gid(%s) for %s failed\n", 00498 sid_string_static(&group_sid), groupname)); 00499 goto done; 00500 } 00501 00502 /* 00503 * If the user has been forced and the forced group starts with a '+', 00504 * then we only set the group to be the forced group if the forced 00505 * user is a member of that group. Otherwise, the meaning of the '+' 00506 * would be ignored. 00507 */ 00508 00509 if (force_user && user_must_be_member) { 00510 if (user_in_group_sid(username, &group_sid)) { 00511 sid_copy(pgroup_sid, &group_sid); 00512 *pgid = gid; 00513 DEBUG(3,("Forced group %s for member %s\n", 00514 groupname, username)); 00515 } else { 00516 DEBUG(0,("find_forced_group: forced user %s is not a member " 00517 "of forced group %s. Disallowing access.\n", 00518 username, groupname )); 00519 result = NT_STATUS_MEMBER_NOT_IN_GROUP; 00520 goto done; 00521 } 00522 } else { 00523 sid_copy(pgroup_sid, &group_sid); 00524 *pgid = gid; 00525 DEBUG(3,("Forced group %s\n", groupname)); 00526 } 00527 00528 result = NT_STATUS_OK; 00529 done: 00530 TALLOC_FREE(mem_ctx); 00531 return result; 00532 }
static connection_struct* make_connection_snum | ( | int | snum, | |
user_struct * | vuser, | |||
DATA_BLOB | password, | |||
const char * | pdev, | |||
NTSTATUS * | status | |||
) | [static] |
参照先 add_gid_to_array_unique()・add_session_user()・connection_struct::admin_user・connection_struct::aio_write_behind_list・authorise_login()・connection_struct::case_preserve・connection_struct::case_sensitive・client_addr()・connection_struct::client_address・conn_free()・conn_new()・create_token_from_username()・dev・connection_struct::dirpath・connection_struct::dirptr・dup_nt_token()・find_forced_group()・find_forced_user()・connection_struct::force_group・connection_struct::force_user・Get_Pwnam()・getpwnam_alloc()・user_struct::gid・connection_struct::gid・connection_struct::groups・user_struct::guest・connection_struct::hide_list・connection_struct::ipc・connection_struct::lastused・connection_struct::lastused_count・connection_struct::mem_ctx・connection_struct::ngroups・user_struct::nt_user_token・connection_struct::nt_user_token・connection_struct::num_files_open・nt_user_token::num_sids・connection_struct::params・password・connection_struct::printer・connection_struct::read_only・SEC_SHARE・share_params::service・share_sanity_checks()・connection_struct::short_case_preserve・sid_copy()・sid_string_static()・sid_to_gid()・status・strequal()・string_set()・user_struct::uid・connection_struct::uid・userdom_struct::unix_name・connection_struct::used・user_struct::user・connection_struct::user・user_ok_token()・nt_user_token::user_sids・connection_struct::veto_list・connection_struct::veto_oplock_list・user_struct::vuid・connection_struct::vuid.
参照元 make_connection().
00543 { 00544 struct passwd *pass = NULL; 00545 BOOL guest = False; 00546 connection_struct *conn; 00547 SMB_STRUCT_STAT st; 00548 fstring user; 00549 fstring dev; 00550 int ret; 00551 00552 *user = 0; 00553 fstrcpy(dev, pdev); 00554 SET_STAT_INVALID(st); 00555 00556 if (NT_STATUS_IS_ERR(*status = share_sanity_checks(snum, dev))) { 00557 return NULL; 00558 } 00559 00560 conn = conn_new(); 00561 if (!conn) { 00562 DEBUG(0,("Couldn't find free connection.\n")); 00563 *status = NT_STATUS_INSUFFICIENT_RESOURCES; 00564 return NULL; 00565 } 00566 00567 conn->params->service = snum; 00568 conn->nt_user_token = NULL; 00569 00570 if (lp_guest_only(snum)) { 00571 const char *guestname = lp_guestaccount(); 00572 NTSTATUS status2; 00573 char *found_username = NULL; 00574 00575 guest = True; 00576 pass = getpwnam_alloc(NULL, guestname); 00577 if (!pass) { 00578 DEBUG(0,("make_connection_snum: Invalid guest " 00579 "account %s??\n",guestname)); 00580 conn_free(conn); 00581 *status = NT_STATUS_NO_SUCH_USER; 00582 return NULL; 00583 } 00584 status2 = create_token_from_username(conn->mem_ctx, pass->pw_name, True, 00585 &conn->uid, &conn->gid, 00586 &found_username, 00587 &conn->nt_user_token); 00588 if (!NT_STATUS_IS_OK(status2)) { 00589 TALLOC_FREE(pass); 00590 conn_free(conn); 00591 *status = status2; 00592 return NULL; 00593 } 00594 fstrcpy(user, found_username); 00595 string_set(&conn->user,user); 00596 conn->force_user = True; 00597 TALLOC_FREE(found_username); 00598 TALLOC_FREE(pass); 00599 DEBUG(3,("Guest only user %s\n",user)); 00600 } else if (vuser) { 00601 if (vuser->guest) { 00602 if (!lp_guest_ok(snum)) { 00603 DEBUG(2, ("guest user (from session setup) " 00604 "not permitted to access this share " 00605 "(%s)\n", lp_servicename(snum))); 00606 conn_free(conn); 00607 *status = NT_STATUS_ACCESS_DENIED; 00608 return NULL; 00609 } 00610 } else { 00611 if (!user_ok_token(vuser->user.unix_name, 00612 vuser->nt_user_token, snum)) { 00613 DEBUG(2, ("user '%s' (from session setup) not " 00614 "permitted to access this share " 00615 "(%s)\n", vuser->user.unix_name, 00616 lp_servicename(snum))); 00617 conn_free(conn); 00618 *status = NT_STATUS_ACCESS_DENIED; 00619 return NULL; 00620 } 00621 } 00622 conn->vuid = vuser->vuid; 00623 conn->uid = vuser->uid; 00624 conn->gid = vuser->gid; 00625 string_set(&conn->user,vuser->user.unix_name); 00626 fstrcpy(user,vuser->user.unix_name); 00627 guest = vuser->guest; 00628 } else if (lp_security() == SEC_SHARE) { 00629 NTSTATUS status2; 00630 char *found_username = NULL; 00631 00632 /* add it as a possible user name if we 00633 are in share mode security */ 00634 add_session_user(lp_servicename(snum)); 00635 /* shall we let them in? */ 00636 if (!authorise_login(snum,user,password,&guest)) { 00637 DEBUG( 2, ( "Invalid username/password for [%s]\n", 00638 lp_servicename(snum)) ); 00639 conn_free(conn); 00640 *status = NT_STATUS_WRONG_PASSWORD; 00641 return NULL; 00642 } 00643 pass = Get_Pwnam(user); 00644 status2 = create_token_from_username(conn->mem_ctx, pass->pw_name, True, 00645 &conn->uid, &conn->gid, 00646 &found_username, 00647 &conn->nt_user_token); 00648 if (!NT_STATUS_IS_OK(status2)) { 00649 conn_free(conn); 00650 *status = status2; 00651 return NULL; 00652 } 00653 fstrcpy(user, found_username); 00654 string_set(&conn->user,user); 00655 TALLOC_FREE(found_username); 00656 conn->force_user = True; 00657 } else { 00658 DEBUG(0, ("invalid VUID (vuser) but not in security=share\n")); 00659 conn_free(conn); 00660 *status = NT_STATUS_ACCESS_DENIED; 00661 return NULL; 00662 } 00663 00664 add_session_user(user); 00665 00666 safe_strcpy(conn->client_address, client_addr(), 00667 sizeof(conn->client_address)-1); 00668 conn->num_files_open = 0; 00669 conn->lastused = conn->lastused_count = time(NULL); 00670 conn->used = True; 00671 conn->printer = (strncmp(dev,"LPT",3) == 0); 00672 conn->ipc = ( (strncmp(dev,"IPC",3) == 0) || 00673 ( lp_enable_asu_support() && strequal(dev,"ADMIN$")) ); 00674 conn->dirptr = NULL; 00675 00676 /* Case options for the share. */ 00677 if (lp_casesensitive(snum) == Auto) { 00678 /* We will be setting this per packet. Set to be case 00679 * insensitive for now. */ 00680 conn->case_sensitive = False; 00681 } else { 00682 conn->case_sensitive = (BOOL)lp_casesensitive(snum); 00683 } 00684 00685 conn->case_preserve = lp_preservecase(snum); 00686 conn->short_case_preserve = lp_shortpreservecase(snum); 00687 00688 conn->veto_list = NULL; 00689 conn->hide_list = NULL; 00690 conn->veto_oplock_list = NULL; 00691 conn->aio_write_behind_list = NULL; 00692 string_set(&conn->dirpath,""); 00693 string_set(&conn->user,user); 00694 00695 conn->read_only = lp_readonly(SNUM(conn)); 00696 conn->admin_user = False; 00697 00698 /* 00699 * If force user is true, then store the given userid and the gid of 00700 * the user we're forcing. 00701 * For auxiliary groups see below. 00702 */ 00703 00704 if (*lp_force_user(snum)) { 00705 NTSTATUS status2; 00706 00707 status2 = find_forced_user(conn, 00708 (vuser != NULL) && vuser->guest, 00709 user); 00710 if (!NT_STATUS_IS_OK(status2)) { 00711 conn_free(conn); 00712 *status = status2; 00713 return NULL; 00714 } 00715 string_set(&conn->user,user); 00716 conn->force_user = True; 00717 DEBUG(3,("Forced user %s\n",user)); 00718 } 00719 00720 /* 00721 * If force group is true, then override 00722 * any groupid stored for the connecting user. 00723 */ 00724 00725 if (*lp_force_group(snum)) { 00726 NTSTATUS status2; 00727 DOM_SID group_sid; 00728 00729 status2 = find_forced_group(conn->force_user, 00730 snum, user, 00731 &group_sid, &conn->gid); 00732 if (!NT_STATUS_IS_OK(status2)) { 00733 conn_free(conn); 00734 *status = status2; 00735 return NULL; 00736 } 00737 00738 if ((conn->nt_user_token == NULL) && (vuser != NULL)) { 00739 00740 /* Not force user and not security=share, but force 00741 * group. vuser has a token to copy */ 00742 00743 conn->nt_user_token = dup_nt_token( 00744 NULL, vuser->nt_user_token); 00745 if (conn->nt_user_token == NULL) { 00746 DEBUG(0, ("dup_nt_token failed\n")); 00747 conn_free(conn); 00748 *status = NT_STATUS_NO_MEMORY; 00749 return NULL; 00750 } 00751 } 00752 00753 /* If conn->nt_user_token is still NULL, we have 00754 * security=share. This means ignore the SID, as we had no 00755 * vuser to copy from */ 00756 00757 if (conn->nt_user_token != NULL) { 00758 /* Overwrite the primary group sid */ 00759 sid_copy(&conn->nt_user_token->user_sids[1], 00760 &group_sid); 00761 00762 } 00763 conn->force_group = True; 00764 } 00765 00766 if (conn->nt_user_token != NULL) { 00767 size_t i; 00768 00769 /* We have a share-specific token from force [user|group]. 00770 * This means we have to create the list of unix groups from 00771 * the list of sids. */ 00772 00773 conn->ngroups = 0; 00774 conn->groups = NULL; 00775 00776 for (i=0; i<conn->nt_user_token->num_sids; i++) { 00777 gid_t gid; 00778 DOM_SID *sid = &conn->nt_user_token->user_sids[i]; 00779 00780 if (!sid_to_gid(sid, &gid)) { 00781 DEBUG(10, ("Could not convert SID %s to gid, " 00782 "ignoring it\n", 00783 sid_string_static(sid))); 00784 continue; 00785 } 00786 if (!add_gid_to_array_unique(conn->mem_ctx, gid, &conn->groups, 00787 &conn->ngroups)) { 00788 DEBUG(0, ("add_gid_to_array_unique failed\n")); 00789 conn_free(conn); 00790 *status = NT_STATUS_NO_MEMORY; 00791 return NULL; 00792 } 00793 } 00794 } 00795 00796 { 00797 pstring s; 00798 pstrcpy(s,lp_pathname(snum)); 00799 standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user, 00800 conn->connectpath, conn->gid, 00801 get_current_username(), 00802 current_user_info.domain, 00803 s, sizeof(s)); 00804 set_conn_connectpath(conn,s); 00805 DEBUG(3,("Connect path is '%s' for service [%s]\n",s, 00806 lp_servicename(snum))); 00807 } 00808 00809 /* 00810 * New code to check if there's a share security descripter 00811 * added from NT server manager. This is done after the 00812 * smb.conf checks are done as we need a uid and token. JRA. 00813 * 00814 */ 00815 00816 { 00817 BOOL can_write = False; 00818 NT_USER_TOKEN *token = conn->nt_user_token ? 00819 conn->nt_user_token : 00820 (vuser ? vuser->nt_user_token : NULL); 00821 00822 /* 00823 * I don't believe this can happen. But the 00824 * logic above is convoluted enough to confuse 00825 * automated checkers, so be sure. JRA. 00826 */ 00827 00828 if (token == NULL) { 00829 DEBUG(0,("make_connection: connection to %s " 00830 "denied due to missing " 00831 "NT token.\n", 00832 lp_servicename(snum))); 00833 conn_free(conn); 00834 *status = NT_STATUS_ACCESS_DENIED; 00835 return NULL; 00836 } 00837 00838 can_write = share_access_check(token, 00839 lp_servicename(snum), 00840 FILE_WRITE_DATA); 00841 00842 if (!can_write) { 00843 if (!share_access_check(token, 00844 lp_servicename(snum), 00845 FILE_READ_DATA)) { 00846 /* No access, read or write. */ 00847 DEBUG(0,("make_connection: connection to %s " 00848 "denied due to security " 00849 "descriptor.\n", 00850 lp_servicename(snum))); 00851 conn_free(conn); 00852 *status = NT_STATUS_ACCESS_DENIED; 00853 return NULL; 00854 } else { 00855 conn->read_only = True; 00856 } 00857 } 00858 } 00859 /* Initialise VFS function pointers */ 00860 00861 if (!smbd_vfs_init(conn)) { 00862 DEBUG(0, ("vfs_init failed for service %s\n", 00863 lp_servicename(snum))); 00864 conn_free(conn); 00865 *status = NT_STATUS_BAD_NETWORK_NAME; 00866 return NULL; 00867 } 00868 00869 /* 00870 * If widelinks are disallowed we need to canonicalise the connect 00871 * path here to ensure we don't have any symlinks in the 00872 * connectpath. We will be checking all paths on this connection are 00873 * below this directory. We must do this after the VFS init as we 00874 * depend on the realpath() pointer in the vfs table. JRA. 00875 */ 00876 if (!lp_widelinks(snum)) { 00877 pstring s; 00878 pstrcpy(s,conn->connectpath); 00879 canonicalize_path(conn, s); 00880 set_conn_connectpath(conn,s); 00881 } 00882 00883 if ((!conn->printer) && (!conn->ipc)) { 00884 conn->notify_ctx = notify_init(conn->mem_ctx, server_id_self(), 00885 smbd_messaging_context(), 00886 smbd_event_context(), 00887 conn); 00888 } 00889 00890 /* ROOT Activities: */ 00891 /* check number of connections */ 00892 if (!claim_connection(conn, 00893 lp_servicename(snum), 00894 lp_max_connections(snum), 00895 False,0)) { 00896 DEBUG(1,("too many connections - rejected\n")); 00897 conn_free(conn); 00898 *status = NT_STATUS_INSUFFICIENT_RESOURCES; 00899 return NULL; 00900 } 00901 00902 /* Preexecs are done here as they might make the dir we are to ChDir 00903 * to below */ 00904 /* execute any "root preexec = " line */ 00905 if (*lp_rootpreexec(snum)) { 00906 pstring cmd; 00907 pstrcpy(cmd,lp_rootpreexec(snum)); 00908 standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user, 00909 conn->connectpath, conn->gid, 00910 get_current_username(), 00911 current_user_info.domain, 00912 cmd, sizeof(cmd)); 00913 DEBUG(5,("cmd=%s\n",cmd)); 00914 ret = smbrun(cmd,NULL); 00915 if (ret != 0 && lp_rootpreexec_close(snum)) { 00916 DEBUG(1,("root preexec gave %d - failing " 00917 "connection\n", ret)); 00918 yield_connection(conn, lp_servicename(snum)); 00919 conn_free(conn); 00920 *status = NT_STATUS_ACCESS_DENIED; 00921 return NULL; 00922 } 00923 } 00924 00925 /* USER Activites: */ 00926 if (!change_to_user(conn, conn->vuid)) { 00927 /* No point continuing if they fail the basic checks */ 00928 DEBUG(0,("Can't become connected user!\n")); 00929 yield_connection(conn, lp_servicename(snum)); 00930 conn_free(conn); 00931 *status = NT_STATUS_LOGON_FAILURE; 00932 return NULL; 00933 } 00934 00935 /* Remember that a different vuid can connect later without these 00936 * checks... */ 00937 00938 /* Preexecs are done here as they might make the dir we are to ChDir 00939 * to below */ 00940 00941 /* execute any "preexec = " line */ 00942 if (*lp_preexec(snum)) { 00943 pstring cmd; 00944 pstrcpy(cmd,lp_preexec(snum)); 00945 standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user, 00946 conn->connectpath, conn->gid, 00947 get_current_username(), 00948 current_user_info.domain, 00949 cmd, sizeof(cmd)); 00950 ret = smbrun(cmd,NULL); 00951 if (ret != 0 && lp_preexec_close(snum)) { 00952 DEBUG(1,("preexec gave %d - failing connection\n", 00953 ret)); 00954 change_to_root_user(); 00955 yield_connection(conn, lp_servicename(snum)); 00956 conn_free(conn); 00957 *status = NT_STATUS_ACCESS_DENIED; 00958 return NULL; 00959 } 00960 } 00961 00962 #ifdef WITH_FAKE_KASERVER 00963 if (lp_afs_share(snum)) { 00964 afs_login(conn); 00965 } 00966 #endif 00967 00968 /* Add veto/hide lists */ 00969 if (!IS_IPC(conn) && !IS_PRINT(conn)) { 00970 set_namearray( &conn->veto_list, lp_veto_files(snum)); 00971 set_namearray( &conn->hide_list, lp_hide_files(snum)); 00972 set_namearray( &conn->veto_oplock_list, lp_veto_oplocks(snum)); 00973 } 00974 00975 /* Invoke VFS make connection hook - do this before the VFS_STAT call 00976 to allow any filesystems needing user credentials to initialize 00977 themselves. */ 00978 00979 if (SMB_VFS_CONNECT(conn, lp_servicename(snum), user) < 0) { 00980 DEBUG(0,("make_connection: VFS make connection failed!\n")); 00981 change_to_root_user(); 00982 yield_connection(conn, lp_servicename(snum)); 00983 conn_free(conn); 00984 *status = NT_STATUS_UNSUCCESSFUL; 00985 return NULL; 00986 } 00987 00988 /* win2000 does not check the permissions on the directory 00989 during the tree connect, instead relying on permission 00990 check during individual operations. To match this behaviour 00991 I have disabled this chdir check (tridge) */ 00992 /* the alternative is just to check the directory exists */ 00993 if ((ret = SMB_VFS_STAT(conn, conn->connectpath, &st)) != 0 || 00994 !S_ISDIR(st.st_mode)) { 00995 if (ret == 0 && !S_ISDIR(st.st_mode)) { 00996 DEBUG(0,("'%s' is not a directory, when connecting to " 00997 "[%s]\n", conn->connectpath, 00998 lp_servicename(snum))); 00999 } else { 01000 DEBUG(0,("'%s' does not exist or permission denied " 01001 "when connecting to [%s] Error was %s\n", 01002 conn->connectpath, lp_servicename(snum), 01003 strerror(errno) )); 01004 } 01005 change_to_root_user(); 01006 /* Call VFS disconnect hook */ 01007 SMB_VFS_DISCONNECT(conn); 01008 yield_connection(conn, lp_servicename(snum)); 01009 conn_free(conn); 01010 *status = NT_STATUS_BAD_NETWORK_NAME; 01011 return NULL; 01012 } 01013 01014 string_set(&conn->origpath,conn->connectpath); 01015 01016 #if SOFTLINK_OPTIMISATION 01017 /* resolve any soft links early if possible */ 01018 if (vfs_ChDir(conn,conn->connectpath) == 0) { 01019 pstring s; 01020 pstrcpy(s,conn->connectpath); 01021 vfs_GetWd(conn,s); 01022 set_conn_connectpath(conn,s); 01023 vfs_ChDir(conn,conn->connectpath); 01024 } 01025 #endif 01026 01027 /* 01028 * Print out the 'connected as' stuff here as we need 01029 * to know the effective uid and gid we will be using 01030 * (at least initially). 01031 */ 01032 01033 if( DEBUGLVL( IS_IPC(conn) ? 3 : 1 ) ) { 01034 dbgtext( "%s (%s) ", get_remote_machine_name(), 01035 conn->client_address ); 01036 dbgtext( "%s", srv_is_signing_active() ? "signed " : ""); 01037 dbgtext( "connect to service %s ", lp_servicename(snum) ); 01038 dbgtext( "initially as user %s ", user ); 01039 dbgtext( "(uid=%d, gid=%d) ", (int)geteuid(), (int)getegid() ); 01040 dbgtext( "(pid %d)\n", (int)sys_getpid() ); 01041 } 01042 01043 /* we've finished with the user stuff - go back to root */ 01044 change_to_root_user(); 01045 return(conn); 01046 }
connection_struct* make_connection_with_chdir | ( | const char * | service_in, | |
DATA_BLOB | password, | |||
const char * | dev, | |||
uint16 | vuid, | |||
NTSTATUS * | status | |||
) |
参照先 conn_free()・connection_struct::connectpath・errno・make_connection()・password・status・strerror()・vfs_ChDir()・yield_connection().
参照元 delete_driver_files()・get_correct_cversion()・move_driver_to_download_area().
01057 { 01058 connection_struct *conn = NULL; 01059 01060 conn = make_connection(service_in, password, dev, vuid, status); 01061 01062 /* 01063 * make_connection() does not change the directory for us any more 01064 * so we have to do it as a separate step --jerry 01065 */ 01066 01067 if ( conn && vfs_ChDir(conn,conn->connectpath) != 0 ) { 01068 DEBUG(0,("move_driver_to_download_area: Can't change " 01069 "directory to %s for [print$] (%s)\n", 01070 conn->connectpath,strerror(errno))); 01071 yield_connection(conn, lp_servicename(SNUM(conn))); 01072 conn_free(conn); 01073 *status = NT_STATUS_UNSUCCESSFUL; 01074 return NULL; 01075 } 01076 01077 return conn; 01078 }
connection_struct* make_connection | ( | const char * | service_in, | |
DATA_BLOB | password, | |||
const char * | pdev, | |||
uint16 | vuid, | |||
NTSTATUS * | status | |||
) |
参照先 client_addr()・conn_num_open()・current_user_info・data_blob()・dev・find_service()・get_remote_machine_name()・get_valid_user_struct()・user_struct::homes_snum・make_connection_snum()・map_username()・non_root_mode()・password・SEC_SHARE・userdom_struct::smb_name・smb_panic()・status・strequal()・strlower_m().
参照元 _srv_net_file_query_secdesc()・_srv_net_file_set_secdesc()・make_connection_with_chdir()・reply_tcon()・reply_tcon_and_X().
01089 { 01090 uid_t euid; 01091 user_struct *vuser = NULL; 01092 fstring service; 01093 fstring dev; 01094 int snum = -1; 01095 01096 fstrcpy(dev, pdev); 01097 01098 /* This must ONLY BE CALLED AS ROOT. As it exits this function as 01099 * root. */ 01100 if (!non_root_mode() && (euid = geteuid()) != 0) { 01101 DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot " 01102 "(%u)\n", (unsigned int)euid )); 01103 smb_panic("make_connection: PANIC ERROR. Called as nonroot\n"); 01104 } 01105 01106 if (conn_num_open() > 2047) { 01107 *status = NT_STATUS_INSUFF_SERVER_RESOURCES; 01108 return NULL; 01109 } 01110 01111 if(lp_security() != SEC_SHARE) { 01112 vuser = get_valid_user_struct(vuid); 01113 if (!vuser) { 01114 DEBUG(1,("make_connection: refusing to connect with " 01115 "no session setup\n")); 01116 *status = NT_STATUS_ACCESS_DENIED; 01117 return NULL; 01118 } 01119 } 01120 01121 /* Logic to try and connect to the correct [homes] share, preferably 01122 without too many getpwnam() lookups. This is particulary nasty for 01123 winbind usernames, where the share name isn't the same as unix 01124 username. 01125 01126 The snum of the homes share is stored on the vuser at session setup 01127 time. 01128 */ 01129 01130 if (strequal(service_in,HOMES_NAME)) { 01131 if(lp_security() != SEC_SHARE) { 01132 DATA_BLOB no_pw = data_blob(NULL, 0); 01133 if (vuser->homes_snum == -1) { 01134 DEBUG(2, ("[homes] share not available for " 01135 "this user because it was not found " 01136 "or created at session setup " 01137 "time\n")); 01138 *status = NT_STATUS_BAD_NETWORK_NAME; 01139 return NULL; 01140 } 01141 DEBUG(5, ("making a connection to [homes] service " 01142 "created at session setup time\n")); 01143 return make_connection_snum(vuser->homes_snum, 01144 vuser, no_pw, 01145 dev, status); 01146 } else { 01147 /* Security = share. Try with 01148 * current_user_info.smb_name as the username. */ 01149 if (*current_user_info.smb_name) { 01150 fstring unix_username; 01151 fstrcpy(unix_username, 01152 current_user_info.smb_name); 01153 map_username(unix_username); 01154 snum = find_service(unix_username); 01155 } 01156 if (snum != -1) { 01157 DEBUG(5, ("making a connection to 'homes' " 01158 "service %s based on " 01159 "security=share\n", service_in)); 01160 return make_connection_snum(snum, NULL, 01161 password, 01162 dev, status); 01163 } 01164 } 01165 } else if ((lp_security() != SEC_SHARE) && (vuser->homes_snum != -1) 01166 && strequal(service_in, 01167 lp_servicename(vuser->homes_snum))) { 01168 DATA_BLOB no_pw = data_blob(NULL, 0); 01169 DEBUG(5, ("making a connection to 'homes' service [%s] " 01170 "created at session setup time\n", service_in)); 01171 return make_connection_snum(vuser->homes_snum, 01172 vuser, no_pw, 01173 dev, status); 01174 } 01175 01176 fstrcpy(service, service_in); 01177 01178 strlower_m(service); 01179 01180 snum = find_service(service); 01181 01182 if (snum < 0) { 01183 if (strequal(service,"IPC$") || 01184 (lp_enable_asu_support() && strequal(service,"ADMIN$"))) { 01185 DEBUG(3,("refusing IPC connection to %s\n", service)); 01186 *status = NT_STATUS_ACCESS_DENIED; 01187 return NULL; 01188 } 01189 01190 DEBUG(0,("%s (%s) couldn't find service %s\n", 01191 get_remote_machine_name(), client_addr(), service)); 01192 *status = NT_STATUS_BAD_NETWORK_NAME; 01193 return NULL; 01194 } 01195 01196 /* Handle non-Dfs clients attempting connections to msdfs proxy */ 01197 if (lp_host_msdfs() && (*lp_msdfs_proxy(snum) != '\0')) { 01198 DEBUG(3, ("refusing connection to dfs proxy share '%s' " 01199 "(pointing to %s)\n", 01200 service, lp_msdfs_proxy(snum))); 01201 *status = NT_STATUS_BAD_NETWORK_NAME; 01202 return NULL; 01203 } 01204 01205 DEBUG(5, ("making a connection to 'normal' service %s\n", service)); 01206 01207 return make_connection_snum(snum, vuser, 01208 password, 01209 dev, status); 01210 }
void close_cnum | ( | connection_struct * | conn, | |
uint16 | vuid | |||
) |
参照先 change_to_root_user()・change_to_user()・connection_struct::client_address・conn_free()・connection_struct::connectpath・current_user_info・userdom_struct::domain・dptr_closecnum()・file_close_conn()・get_current_username()・get_remote_machine_name()・connection_struct::gid・pipe_close_conn()・smbrun()・standard_sub_advanced()・connection_struct::user・vfs_ChDir()・yield_connection().
参照元 _srv_net_file_query_secdesc()・_srv_net_file_set_secdesc()・conn_close_all()・get_correct_cversion()・handle_trans()・msg_force_tdis()・reply_tcon_and_X()・reply_tdis().
01217 { 01218 if (IS_IPC(conn)) { 01219 pipe_close_conn(conn); 01220 } else { 01221 file_close_conn(conn); 01222 dptr_closecnum(conn); 01223 } 01224 01225 change_to_root_user(); 01226 01227 DEBUG(IS_IPC(conn)?3:1, ("%s (%s) closed connection to service %s\n", 01228 get_remote_machine_name(), 01229 conn->client_address, 01230 lp_servicename(SNUM(conn)))); 01231 01232 /* Call VFS disconnect hook */ 01233 SMB_VFS_DISCONNECT(conn); 01234 01235 yield_connection(conn, lp_servicename(SNUM(conn))); 01236 01237 /* make sure we leave the directory available for unmount */ 01238 vfs_ChDir(conn, "/"); 01239 01240 /* execute any "postexec = " line */ 01241 if (*lp_postexec(SNUM(conn)) && 01242 change_to_user(conn, vuid)) { 01243 pstring cmd; 01244 pstrcpy(cmd,lp_postexec(SNUM(conn))); 01245 standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user, 01246 conn->connectpath, conn->gid, 01247 get_current_username(), 01248 current_user_info.domain, 01249 cmd, sizeof(cmd)); 01250 smbrun(cmd,NULL); 01251 change_to_root_user(); 01252 } 01253 01254 change_to_root_user(); 01255 /* execute any "root postexec = " line */ 01256 if (*lp_rootpostexec(SNUM(conn))) { 01257 pstring cmd; 01258 pstrcpy(cmd,lp_rootpostexec(SNUM(conn))); 01259 standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user, 01260 conn->connectpath, conn->gid, 01261 get_current_username(), 01262 current_user_info.domain, 01263 cmd, sizeof(cmd)); 01264 smbrun(cmd,NULL); 01265 } 01266 01267 conn_free(conn); 01268 }
substitute.c の 29 行で定義されています。