root/source3/smbd/service.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. canonicalize_connect_path
  2. set_conn_connectpath
  3. set_current_service
  4. load_registry_service
  5. load_registry_shares
  6. add_home_service
  7. find_service
  8. share_sanity_checks
  9. find_forced_group
  10. create_connection_server_info
  11. make_connection_snum
  12. make_connection
  13. close_cnum

   1 /* 
   2    Unix SMB/CIFS implementation.
   3    service (connection) opening and closing
   4    Copyright (C) Andrew Tridgell 1992-1998
   5    
   6    This program is free software; you can redistribute it and/or modify
   7    it under the terms of the GNU General Public License as published by
   8    the Free Software Foundation; either version 3 of the License, or
   9    (at your option) any later version.
  10    
  11    This program is distributed in the hope that it will be useful,
  12    but WITHOUT ANY WARRANTY; without even the implied warranty of
  13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14    GNU General Public License for more details.
  15    
  16    You should have received a copy of the GNU General Public License
  17    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  18 */
  19 
  20 #include "includes.h"
  21 #include "smbd/globals.h"
  22 
  23 extern userdom_struct current_user_info;
  24 
  25 static bool canonicalize_connect_path(connection_struct *conn)
     /* [<][>][^][v][top][bottom][index][help] */
  26 {
  27 #ifdef REALPATH_TAKES_NULL
  28         bool ret;
  29         char *resolved_name = SMB_VFS_REALPATH(conn,conn->connectpath,NULL);
  30         if (!resolved_name) {
  31                 return false;
  32         }
  33         ret = set_conn_connectpath(conn,resolved_name);
  34         SAFE_FREE(resolved_name);
  35         return ret;
  36 #else
  37         char resolved_name_buf[PATH_MAX+1];
  38         char *resolved_name = SMB_VFS_REALPATH(conn,conn->connectpath,resolved_name_buf);
  39         if (!resolved_name) {
  40                 return false;
  41         }
  42         return set_conn_connectpath(conn,resolved_name);
  43 #endif /* REALPATH_TAKES_NULL */
  44 }
  45 
  46 /****************************************************************************
  47  Ensure when setting connectpath it is a canonicalized (no ./ // or ../)
  48  absolute path stating in / and not ending in /.
  49  Observent people will notice a similarity between this and check_path_syntax :-).
  50 ****************************************************************************/
  51 
  52 bool set_conn_connectpath(connection_struct *conn, const char *connectpath)
     /* [<][>][^][v][top][bottom][index][help] */
  53 {
  54         char *destname;
  55         char *d;
  56         const char *s = connectpath;
  57         bool start_of_name_component = true;
  58 
  59         if (connectpath == NULL || connectpath[0] == '\0') {
  60                 return false;
  61         }
  62 
  63         destname = SMB_STRDUP(connectpath);
  64         if (!destname) {
  65                 return false;
  66         }
  67         d = destname;
  68 
  69         *d++ = '/'; /* Always start with root. */
  70 
  71         while (*s) {
  72                 if (*s == '/') {
  73                         /* Eat multiple '/' */
  74                         while (*s == '/') {
  75                                 s++;
  76                         }
  77                         if ((d > destname + 1) && (*s != '\0')) {
  78                                 *d++ = '/';
  79                         }
  80                         start_of_name_component = True;
  81                         continue;
  82                 }
  83 
  84                 if (start_of_name_component) {
  85                         if ((s[0] == '.') && (s[1] == '.') && (s[2] == '/' || s[2] == '\0')) {
  86                                 /* Uh oh - "/../" or "/..\0" ! */
  87 
  88                                 /* Go past the ../ or .. */
  89                                 if (s[2] == '/') {
  90                                         s += 3;
  91                                 } else {
  92                                         s += 2; /* Go past the .. */
  93                                 }
  94 
  95                                 /* If  we just added a '/' - delete it */
  96                                 if ((d > destname) && (*(d-1) == '/')) {
  97                                         *(d-1) = '\0';
  98                                         d--;
  99                                 }
 100 
 101                                 /* Are we at the start ? Can't go back further if so. */
 102                                 if (d <= destname) {
 103                                         *d++ = '/'; /* Can't delete root */
 104                                         continue;
 105                                 }
 106                                 /* Go back one level... */
 107                                 /* Decrement d first as d points to the *next* char to write into. */
 108                                 for (d--; d > destname; d--) {
 109                                         if (*d == '/') {
 110                                                 break;
 111                                         }
 112                                 }
 113                                 /* We're still at the start of a name component, just the previous one. */
 114                                 continue;
 115                         } else if ((s[0] == '.') && ((s[1] == '\0') || s[1] == '/')) {
 116                                 /* Component of pathname can't be "." only - skip the '.' . */
 117                                 if (s[1] == '/') {
 118                                         s += 2;
 119                                 } else {
 120                                         s++;
 121                                 }
 122                                 continue;
 123                         }
 124                 }
 125 
 126                 if (!(*s & 0x80)) {
 127                         *d++ = *s++;
 128                 } else {
 129                         size_t siz;
 130                         /* Get the size of the next MB character. */
 131                         next_codepoint(s,&siz);
 132                         switch(siz) {
 133                                 case 5:
 134                                         *d++ = *s++;
 135                                         /*fall through*/
 136                                 case 4:
 137                                         *d++ = *s++;
 138                                         /*fall through*/
 139                                 case 3:
 140                                         *d++ = *s++;
 141                                         /*fall through*/
 142                                 case 2:
 143                                         *d++ = *s++;
 144                                         /*fall through*/
 145                                 case 1:
 146                                         *d++ = *s++;
 147                                         break;
 148                                 default:
 149                                         break;
 150                         }
 151                 }
 152                 start_of_name_component = false;
 153         }
 154         *d = '\0';
 155 
 156         /* And must not end in '/' */
 157         if (d > destname + 1 && (*(d-1) == '/')) {
 158                 *(d-1) = '\0';
 159         }
 160 
 161         DEBUG(10,("set_conn_connectpath: service %s, connectpath = %s\n",
 162                 lp_servicename(SNUM(conn)), destname ));
 163 
 164         string_set(&conn->connectpath, destname);
 165         SAFE_FREE(destname);
 166         return true;
 167 }
 168 
 169 /****************************************************************************
 170  Load parameters specific to a connection/service.
 171 ****************************************************************************/
 172 
 173 bool set_current_service(connection_struct *conn, uint16 flags, bool do_chdir)
     /* [<][>][^][v][top][bottom][index][help] */
 174 {
 175         int snum;
 176 
 177         if (!conn)  {
 178                 last_conn = NULL;
 179                 return(False);
 180         }
 181 
 182         conn->lastused_count++;
 183 
 184         snum = SNUM(conn);
 185   
 186         if (do_chdir &&
 187             vfs_ChDir(conn,conn->connectpath) != 0 &&
 188             vfs_ChDir(conn,conn->origpath) != 0) {
 189                 DEBUG(0,("chdir (%s) failed\n",
 190                          conn->connectpath));
 191                 return(False);
 192         }
 193 
 194         if ((conn == last_conn) && (last_flags == flags)) {
 195                 return(True);
 196         }
 197 
 198         last_conn = conn;
 199         last_flags = flags;
 200         
 201         /* Obey the client case sensitivity requests - only for clients that support it. */
 202         switch (lp_casesensitive(snum)) {
 203                 case Auto:
 204                         {
 205                                 /* We need this uglyness due to DOS/Win9x clients that lie about case insensitivity. */
 206                                 enum remote_arch_types ra_type = get_remote_arch();
 207                                 if ((ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
 208                                         /* Client can't support per-packet case sensitive pathnames. */
 209                                         conn->case_sensitive = False;
 210                                 } else {
 211                                         conn->case_sensitive = !(flags & FLAG_CASELESS_PATHNAMES);
 212                                 }
 213                         }
 214                         break;
 215                 case True:
 216                         conn->case_sensitive = True;
 217                         break;
 218                 default:
 219                         conn->case_sensitive = False;
 220                         break;
 221         }
 222         return(True);
 223 }
 224 
 225 static int load_registry_service(const char *servicename)
     /* [<][>][^][v][top][bottom][index][help] */
 226 {
 227         if (!lp_registry_shares()) {
 228                 return -1;
 229         }
 230 
 231         if ((servicename == NULL) || (*servicename == '\0')) {
 232                 return -1;
 233         }
 234 
 235         if (strequal(servicename, GLOBAL_NAME)) {
 236                 return -2;
 237         }
 238 
 239         if (!process_registry_service(servicename)) {
 240                 return -1;
 241         }
 242 
 243         return lp_servicenumber(servicename);
 244 }
 245 
 246 void load_registry_shares(void)
     /* [<][>][^][v][top][bottom][index][help] */
 247 {
 248         DEBUG(8, ("load_registry_shares()\n"));
 249         if (!lp_registry_shares()) {
 250                 return;
 251         }
 252 
 253         process_registry_shares();
 254 
 255         return;
 256 }
 257 
 258 /****************************************************************************
 259  Add a home service. Returns the new service number or -1 if fail.
 260 ****************************************************************************/
 261 
 262 int add_home_service(const char *service, const char *username, const char *homedir)
     /* [<][>][^][v][top][bottom][index][help] */
 263 {
 264         int iHomeService;
 265 
 266         if (!service || !homedir || homedir[0] == '\0')
 267                 return -1;
 268 
 269         if ((iHomeService = lp_servicenumber(HOMES_NAME)) < 0) {
 270                 if ((iHomeService = load_registry_service(HOMES_NAME)) < 0) {
 271                         return -1;
 272                 }
 273         }
 274 
 275         /*
 276          * If this is a winbindd provided username, remove
 277          * the domain component before adding the service.
 278          * Log a warning if the "path=" parameter does not
 279          * include any macros.
 280          */
 281 
 282         {
 283                 const char *p = strchr(service,*lp_winbind_separator());
 284 
 285                 /* We only want the 'user' part of the string */
 286                 if (p) {
 287                         service = p + 1;
 288                 }
 289         }
 290 
 291         if (!lp_add_home(service, iHomeService, username, homedir)) {
 292                 return -1;
 293         }
 294         
 295         return lp_servicenumber(service);
 296 
 297 }
 298 
 299 /**
 300  * Find a service entry.
 301  *
 302  * @param service is modified (to canonical form??)
 303  **/
 304 
 305 int find_service(fstring service)
     /* [<][>][^][v][top][bottom][index][help] */
 306 {
 307         int iService;
 308 
 309         all_string_sub(service,"\\","/",0);
 310 
 311         iService = lp_servicenumber(service);
 312 
 313         /* now handle the special case of a home directory */
 314         if (iService < 0) {
 315                 char *phome_dir = get_user_home_dir(talloc_tos(), service);
 316 
 317                 if(!phome_dir) {
 318                         /*
 319                          * Try mapping the servicename, it may
 320                          * be a Windows to unix mapped user name.
 321                          */
 322                         if(map_username(service))
 323                                 phome_dir = get_user_home_dir(
 324                                         talloc_tos(), service);
 325                 }
 326 
 327                 DEBUG(3,("checking for home directory %s gave %s\n",service,
 328                         phome_dir?phome_dir:"(NULL)"));
 329 
 330                 iService = add_home_service(service,service /* 'username' */, phome_dir);
 331         }
 332 
 333         /* If we still don't have a service, attempt to add it as a printer. */
 334         if (iService < 0) {
 335                 int iPrinterService;
 336 
 337                 if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) < 0) {
 338                         iPrinterService = load_registry_service(PRINTERS_NAME);
 339                 }
 340                 if (iPrinterService) {
 341                         DEBUG(3,("checking whether %s is a valid printer name...\n", service));
 342                         if (pcap_printername_ok(service)) {
 343                                 DEBUG(3,("%s is a valid printer name\n", service));
 344                                 DEBUG(3,("adding %s as a printer service\n", service));
 345                                 lp_add_printer(service, iPrinterService);
 346                                 iService = lp_servicenumber(service);
 347                                 if (iService < 0) {
 348                                         DEBUG(0,("failed to add %s as a printer service!\n", service));
 349                                 }
 350                         } else {
 351                                 DEBUG(3,("%s is not a valid printer name\n", service));
 352                         }
 353                 }
 354         }
 355 
 356         /* Check for default vfs service?  Unsure whether to implement this */
 357         if (iService < 0) {
 358         }
 359 
 360         if (iService < 0) {
 361                 iService = load_registry_service(service);
 362         }
 363 
 364         /* Is it a usershare service ? */
 365         if (iService < 0 && *lp_usershare_path()) {
 366                 /* Ensure the name is canonicalized. */
 367                 strlower_m(service);
 368                 iService = load_usershare_service(service);
 369         }
 370 
 371         /* just possibly it's a default service? */
 372         if (iService < 0) {
 373                 char *pdefservice = lp_defaultservice();
 374                 if (pdefservice && *pdefservice && !strequal(pdefservice,service) && !strstr_m(service,"..")) {
 375                         /*
 376                          * We need to do a local copy here as lp_defaultservice() 
 377                          * returns one of the rotating lp_string buffers that
 378                          * could get overwritten by the recursive find_service() call
 379                          * below. Fix from Josef Hinteregger <joehtg@joehtg.co.at>.
 380                          */
 381                         char *defservice = SMB_STRDUP(pdefservice);
 382 
 383                         if (!defservice) {
 384                                 goto fail;
 385                         }
 386 
 387                         /* Disallow anything except explicit share names. */
 388                         if (strequal(defservice,HOMES_NAME) ||
 389                                         strequal(defservice, PRINTERS_NAME) ||
 390                                         strequal(defservice, "IPC$")) {
 391                                 SAFE_FREE(defservice);
 392                                 goto fail;
 393                         }
 394 
 395                         iService = find_service(defservice);
 396                         if (iService >= 0) {
 397                                 all_string_sub(service, "_","/",0);
 398                                 iService = lp_add_service(service, iService);
 399                         }
 400                         SAFE_FREE(defservice);
 401                 }
 402         }
 403 
 404         if (iService >= 0) {
 405                 if (!VALID_SNUM(iService)) {
 406                         DEBUG(0,("Invalid snum %d for %s\n",iService, service));
 407                         iService = -1;
 408                 }
 409         }
 410 
 411   fail:
 412 
 413         if (iService < 0)
 414                 DEBUG(3,("find_service() failed to find service %s\n", service));
 415 
 416         return (iService);
 417 }
 418 
 419 
 420 /****************************************************************************
 421  do some basic sainity checks on the share.  
 422  This function modifies dev, ecode.
 423 ****************************************************************************/
 424 
 425 static NTSTATUS share_sanity_checks(int snum, fstring dev) 
     /* [<][>][^][v][top][bottom][index][help] */
 426 {
 427         
 428         if (!lp_snum_ok(snum) || 
 429             !check_access(smbd_server_fd(), 
 430                           lp_hostsallow(snum), lp_hostsdeny(snum))) {    
 431                 return NT_STATUS_ACCESS_DENIED;
 432         }
 433 
 434         if (dev[0] == '?' || !dev[0]) {
 435                 if (lp_print_ok(snum)) {
 436                         fstrcpy(dev,"LPT1:");
 437                 } else if (strequal(lp_fstype(snum), "IPC")) {
 438                         fstrcpy(dev, "IPC");
 439                 } else {
 440                         fstrcpy(dev,"A:");
 441                 }
 442         }
 443 
 444         strupper_m(dev);
 445 
 446         if (lp_print_ok(snum)) {
 447                 if (!strequal(dev, "LPT1:")) {
 448                         return NT_STATUS_BAD_DEVICE_TYPE;
 449                 }
 450         } else if (strequal(lp_fstype(snum), "IPC")) {
 451                 if (!strequal(dev, "IPC")) {
 452                         return NT_STATUS_BAD_DEVICE_TYPE;
 453                 }
 454         } else if (!strequal(dev, "A:")) {
 455                 return NT_STATUS_BAD_DEVICE_TYPE;
 456         }
 457 
 458         /* Behave as a printer if we are supposed to */
 459         if (lp_print_ok(snum) && (strcmp(dev, "A:") == 0)) {
 460                 fstrcpy(dev, "LPT1:");
 461         }
 462 
 463         return NT_STATUS_OK;
 464 }
 465 
 466 /*
 467  * Go through lookup_name etc to find the force'd group.  
 468  *
 469  * Create a new token from src_token, replacing the primary group sid with the
 470  * one found.
 471  */
 472 
 473 static NTSTATUS find_forced_group(bool force_user,
     /* [<][>][^][v][top][bottom][index][help] */
 474                                   int snum, const char *username,
 475                                   DOM_SID *pgroup_sid,
 476                                   gid_t *pgid)
 477 {
 478         NTSTATUS result = NT_STATUS_NO_SUCH_GROUP;
 479         TALLOC_CTX *frame = talloc_stackframe();
 480         DOM_SID group_sid;
 481         enum lsa_SidType type;
 482         char *groupname;
 483         bool user_must_be_member = False;
 484         gid_t gid;
 485 
 486         groupname = talloc_strdup(talloc_tos(), lp_force_group(snum));
 487         if (groupname == NULL) {
 488                 DEBUG(1, ("talloc_strdup failed\n"));
 489                 result = NT_STATUS_NO_MEMORY;
 490                 goto done;
 491         }
 492 
 493         if (groupname[0] == '+') {
 494                 user_must_be_member = True;
 495                 groupname += 1;
 496         }
 497 
 498         groupname = talloc_string_sub(talloc_tos(), groupname,
 499                                       "%S", lp_servicename(snum));
 500         if (groupname == NULL) {
 501                 DEBUG(1, ("talloc_string_sub failed\n"));
 502                 result = NT_STATUS_NO_MEMORY;
 503                 goto done;
 504         }
 505 
 506         if (!lookup_name_smbconf(talloc_tos(), groupname,
 507                          LOOKUP_NAME_ALL|LOOKUP_NAME_GROUP,
 508                          NULL, NULL, &group_sid, &type)) {
 509                 DEBUG(10, ("lookup_name_smbconf(%s) failed\n",
 510                            groupname));
 511                 goto done;
 512         }
 513 
 514         if ((type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) &&
 515             (type != SID_NAME_WKN_GRP)) {
 516                 DEBUG(10, ("%s is a %s, not a group\n", groupname,
 517                            sid_type_lookup(type)));
 518                 goto done;
 519         }
 520 
 521         if (!sid_to_gid(&group_sid, &gid)) {
 522                 DEBUG(10, ("sid_to_gid(%s) for %s failed\n",
 523                            sid_string_dbg(&group_sid), groupname));
 524                 goto done;
 525         }
 526 
 527         /*
 528          * If the user has been forced and the forced group starts with a '+',
 529          * then we only set the group to be the forced group if the forced
 530          * user is a member of that group.  Otherwise, the meaning of the '+'
 531          * would be ignored.
 532          */
 533 
 534         if (force_user && user_must_be_member) {
 535                 if (user_in_group_sid(username, &group_sid)) {
 536                         sid_copy(pgroup_sid, &group_sid);
 537                         *pgid = gid;
 538                         DEBUG(3,("Forced group %s for member %s\n",
 539                                  groupname, username));
 540                 } else {
 541                         DEBUG(0,("find_forced_group: forced user %s is not a member "
 542                                 "of forced group %s. Disallowing access.\n",
 543                                 username, groupname ));
 544                         result = NT_STATUS_MEMBER_NOT_IN_GROUP;
 545                         goto done;
 546                 }
 547         } else {
 548                 sid_copy(pgroup_sid, &group_sid);
 549                 *pgid = gid;
 550                 DEBUG(3,("Forced group %s\n", groupname));
 551         }
 552 
 553         result = NT_STATUS_OK;
 554  done:
 555         TALLOC_FREE(frame);
 556         return result;
 557 }
 558 
 559 /****************************************************************************
 560   Create an auth_serversupplied_info structure for a connection_struct
 561 ****************************************************************************/
 562 
 563 static NTSTATUS create_connection_server_info(TALLOC_CTX *mem_ctx, int snum,
     /* [<][>][^][v][top][bottom][index][help] */
 564                                               struct auth_serversupplied_info *vuid_serverinfo,
 565                                               DATA_BLOB password,
 566                                               struct auth_serversupplied_info **presult)
 567 {
 568         if (lp_guest_only(snum)) {
 569                 return make_server_info_guest(mem_ctx, presult);
 570         }
 571 
 572         if (vuid_serverinfo != NULL) {
 573 
 574                 struct auth_serversupplied_info *result;
 575 
 576                 /*
 577                  * This is the normal security != share case where we have a
 578                  * valid vuid from the session setup.                 */
 579 
 580                 if (vuid_serverinfo->guest) {
 581                         if (!lp_guest_ok(snum)) {
 582                                 DEBUG(2, ("guest user (from session setup) "
 583                                           "not permitted to access this share "
 584                                           "(%s)\n", lp_servicename(snum)));
 585                                 return NT_STATUS_ACCESS_DENIED;
 586                         }
 587                 } else {
 588                         if (!user_ok_token(vuid_serverinfo->unix_name,
 589                                            pdb_get_domain(vuid_serverinfo->sam_account),
 590                                            vuid_serverinfo->ptok, snum)) {
 591                                 DEBUG(2, ("user '%s' (from session setup) not "
 592                                           "permitted to access this share "
 593                                           "(%s)\n",
 594                                           vuid_serverinfo->unix_name,
 595                                           lp_servicename(snum)));
 596                                 return NT_STATUS_ACCESS_DENIED;
 597                         }
 598                 }
 599 
 600                 result = copy_serverinfo(mem_ctx, vuid_serverinfo);
 601                 if (result == NULL) {
 602                         return NT_STATUS_NO_MEMORY;
 603                 }
 604 
 605                 *presult = result;
 606                 return NT_STATUS_OK;
 607         }
 608 
 609         if (lp_security() == SEC_SHARE) {
 610 
 611                 fstring user;
 612                 bool guest;
 613 
 614                 /* add the sharename as a possible user name if we
 615                    are in share mode security */
 616 
 617                 add_session_user(lp_servicename(snum));
 618 
 619                 /* shall we let them in? */
 620 
 621                 if (!authorise_login(snum,user,password,&guest)) {
 622                         DEBUG( 2, ( "Invalid username/password for [%s]\n",
 623                                     lp_servicename(snum)) );
 624                         return NT_STATUS_WRONG_PASSWORD;
 625                 }
 626 
 627                 return make_serverinfo_from_username(mem_ctx, user, guest,
 628                                                      presult);
 629         }
 630 
 631         DEBUG(0, ("invalid VUID (vuser) but not in security=share\n"));
 632         return NT_STATUS_ACCESS_DENIED;
 633 }
 634 
 635 
 636 /****************************************************************************
 637   Make a connection, given the snum to connect to, and the vuser of the
 638   connecting user if appropriate.
 639 ****************************************************************************/
 640 
 641 static connection_struct *make_connection_snum(int snum, user_struct *vuser,
     /* [<][>][^][v][top][bottom][index][help] */
 642                                                DATA_BLOB password, 
 643                                                const char *pdev,
 644                                                NTSTATUS *pstatus)
 645 {
 646         connection_struct *conn;
 647         SMB_STRUCT_STAT st;
 648         fstring dev;
 649         int ret;
 650         char addr[INET6_ADDRSTRLEN];
 651         bool on_err_call_dis_hook = false;
 652         NTSTATUS status;
 653 
 654         fstrcpy(dev, pdev);
 655         SET_STAT_INVALID(st);
 656 
 657         if (NT_STATUS_IS_ERR(*pstatus = share_sanity_checks(snum, dev))) {
 658                 return NULL;
 659         }       
 660 
 661         conn = conn_new();
 662         if (!conn) {
 663                 DEBUG(0,("Couldn't find free connection.\n"));
 664                 *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
 665                 return NULL;
 666         }
 667 
 668         conn->params->service = snum;
 669 
 670         status = create_connection_server_info(
 671                 conn, snum, vuser ? vuser->server_info : NULL, password,
 672                 &conn->server_info);
 673 
 674         if (!NT_STATUS_IS_OK(status)) {
 675                 DEBUG(1, ("create_connection_server_info failed: %s\n",
 676                           nt_errstr(status)));
 677                 *pstatus = status;
 678                 conn_free(conn);
 679                 return NULL;
 680         }
 681 
 682         if ((lp_guest_only(snum)) || (lp_security() == SEC_SHARE)) {
 683                 conn->force_user = true;
 684         }
 685 
 686         add_session_user(conn->server_info->unix_name);
 687 
 688         safe_strcpy(conn->client_address,
 689                         client_addr(get_client_fd(),addr,sizeof(addr)), 
 690                         sizeof(conn->client_address)-1);
 691         conn->num_files_open = 0;
 692         conn->lastused = conn->lastused_count = time(NULL);
 693         conn->used = True;
 694         conn->printer = (strncmp(dev,"LPT",3) == 0);
 695         conn->ipc = ( (strncmp(dev,"IPC",3) == 0) ||
 696                       ( lp_enable_asu_support() && strequal(dev,"ADMIN$")) );
 697         conn->dirptr = NULL;
 698 
 699         /* Case options for the share. */
 700         if (lp_casesensitive(snum) == Auto) {
 701                 /* We will be setting this per packet. Set to be case
 702                  * insensitive for now. */
 703                 conn->case_sensitive = False;
 704         } else {
 705                 conn->case_sensitive = (bool)lp_casesensitive(snum);
 706         }
 707 
 708         conn->case_preserve = lp_preservecase(snum);
 709         conn->short_case_preserve = lp_shortpreservecase(snum);
 710 
 711         conn->encrypt_level = lp_smb_encrypt(snum);
 712 
 713         conn->veto_list = NULL;
 714         conn->hide_list = NULL;
 715         conn->veto_oplock_list = NULL;
 716         conn->aio_write_behind_list = NULL;
 717         string_set(&conn->dirpath,"");
 718 
 719         conn->read_only = lp_readonly(SNUM(conn));
 720         conn->admin_user = False;
 721 
 722         if (*lp_force_user(snum)) {
 723 
 724                 /*
 725                  * Replace conn->server_info with a completely faked up one
 726                  * from the username we are forced into :-)
 727                  */
 728 
 729                 char *fuser;
 730                 struct auth_serversupplied_info *forced_serverinfo;
 731 
 732                 fuser = talloc_string_sub(conn, lp_force_user(snum), "%S",
 733                                           lp_servicename(snum));
 734                 if (fuser == NULL) {
 735                         conn_free(conn);
 736                         *pstatus = NT_STATUS_NO_MEMORY;
 737                         return NULL;
 738                 }
 739 
 740                 status = make_serverinfo_from_username(
 741                         conn, fuser, conn->server_info->guest,
 742                         &forced_serverinfo);
 743                 if (!NT_STATUS_IS_OK(status)) {
 744                         conn_free(conn);
 745                         *pstatus = status;
 746                         return NULL;
 747                 }
 748 
 749                 TALLOC_FREE(conn->server_info);
 750                 conn->server_info = forced_serverinfo;
 751 
 752                 conn->force_user = True;
 753                 DEBUG(3,("Forced user %s\n", fuser));
 754         }
 755 
 756         /*
 757          * If force group is true, then override
 758          * any groupid stored for the connecting user.
 759          */
 760 
 761         if (*lp_force_group(snum)) {
 762 
 763                 status = find_forced_group(
 764                         conn->force_user, snum, conn->server_info->unix_name,
 765                         &conn->server_info->ptok->user_sids[1],
 766                         &conn->server_info->utok.gid);
 767 
 768                 if (!NT_STATUS_IS_OK(status)) {
 769                         conn_free(conn);
 770                         *pstatus = status;
 771                         return NULL;
 772                 }
 773 
 774                 /*
 775                  * We need to cache this gid, to use within
 776                  * change_to_user() separately from the conn->server_info
 777                  * struct. We only use conn->server_info directly if
 778                  * "force_user" was set.
 779                  */
 780                 conn->force_group_gid = conn->server_info->utok.gid;
 781         }
 782 
 783         conn->vuid = (vuser != NULL) ? vuser->vuid : UID_FIELD_INVALID;
 784 
 785         {
 786                 char *s = talloc_sub_advanced(talloc_tos(),
 787                                         lp_servicename(SNUM(conn)),
 788                                         conn->server_info->unix_name,
 789                                         conn->connectpath,
 790                                         conn->server_info->utok.gid,
 791                                         conn->server_info->sanitized_username,
 792                                         pdb_get_domain(conn->server_info->sam_account),
 793                                         lp_pathname(snum));
 794                 if (!s) {
 795                         conn_free(conn);
 796                         *pstatus = NT_STATUS_NO_MEMORY;
 797                         return NULL;
 798                 }
 799 
 800                 if (!set_conn_connectpath(conn,s)) {
 801                         TALLOC_FREE(s);
 802                         conn_free(conn);
 803                         *pstatus = NT_STATUS_NO_MEMORY;
 804                         return NULL;
 805                 }
 806                 DEBUG(3,("Connect path is '%s' for service [%s]\n",s,
 807                          lp_servicename(snum)));
 808                 TALLOC_FREE(s);
 809         }
 810 
 811         /*
 812          * New code to check if there's a share security descripter
 813          * added from NT server manager. This is done after the
 814          * smb.conf checks are done as we need a uid and token. JRA.
 815          *
 816          */
 817 
 818         {
 819                 bool can_write = False;
 820 
 821                 can_write = share_access_check(conn->server_info->ptok,
 822                                                lp_servicename(snum),
 823                                                FILE_WRITE_DATA);
 824 
 825                 if (!can_write) {
 826                         if (!share_access_check(conn->server_info->ptok,
 827                                                 lp_servicename(snum),
 828                                                 FILE_READ_DATA)) {
 829                                 /* No access, read or write. */
 830                                 DEBUG(0,("make_connection: connection to %s "
 831                                          "denied due to security "
 832                                          "descriptor.\n",
 833                                           lp_servicename(snum)));
 834                                 conn_free(conn);
 835                                 *pstatus = NT_STATUS_ACCESS_DENIED;
 836                                 return NULL;
 837                         } else {
 838                                 conn->read_only = True;
 839                         }
 840                 }
 841         }
 842         /* Initialise VFS function pointers */
 843 
 844         if (!smbd_vfs_init(conn)) {
 845                 DEBUG(0, ("vfs_init failed for service %s\n",
 846                           lp_servicename(snum)));
 847                 conn_free(conn);
 848                 *pstatus = NT_STATUS_BAD_NETWORK_NAME;
 849                 return NULL;
 850         }
 851 
 852         /*
 853          * If widelinks are disallowed we need to canonicalise the connect
 854          * path here to ensure we don't have any symlinks in the
 855          * connectpath. We will be checking all paths on this connection are
 856          * below this directory. We must do this after the VFS init as we
 857          * depend on the realpath() pointer in the vfs table. JRA.
 858          */
 859         if (!lp_widelinks(snum)) {
 860                 if (!canonicalize_connect_path(conn)) {
 861                         DEBUG(0, ("canonicalize_connect_path failed "
 862                         "for service %s, path %s\n",
 863                                 lp_servicename(snum),
 864                                 conn->connectpath));
 865                         conn_free(conn);
 866                         *pstatus = NT_STATUS_BAD_NETWORK_NAME;
 867                         return NULL;
 868                 }
 869         }
 870 
 871         if ((!conn->printer) && (!conn->ipc)) {
 872                 conn->notify_ctx = notify_init(conn, server_id_self(),
 873                                                smbd_messaging_context(),
 874                                                smbd_event_context(),
 875                                                conn);
 876         }
 877 
 878 /* ROOT Activities: */  
 879         /*
 880          * Enforce the max connections parameter.
 881          */
 882 
 883         if ((lp_max_connections(snum) > 0)
 884             && (count_current_connections(lp_servicename(SNUM(conn)), True) >=
 885                 lp_max_connections(snum))) {
 886 
 887                 DEBUG(1, ("Max connections (%d) exceeded for %s\n",
 888                           lp_max_connections(snum), lp_servicename(snum)));
 889                 conn_free(conn);
 890                 *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
 891                 return NULL;
 892         }  
 893 
 894         /*
 895          * Get us an entry in the connections db
 896          */
 897         if (!claim_connection(conn, lp_servicename(snum), 0)) {
 898                 DEBUG(1, ("Could not store connections entry\n"));
 899                 conn_free(conn);
 900                 *pstatus = NT_STATUS_INTERNAL_DB_ERROR;
 901                 return NULL;
 902         }  
 903 
 904         /* Preexecs are done here as they might make the dir we are to ChDir
 905          * to below */
 906         /* execute any "root preexec = " line */
 907         if (*lp_rootpreexec(snum)) {
 908                 char *cmd = talloc_sub_advanced(talloc_tos(),
 909                                         lp_servicename(SNUM(conn)),
 910                                         conn->server_info->unix_name,
 911                                         conn->connectpath,
 912                                         conn->server_info->utok.gid,
 913                                         conn->server_info->sanitized_username,
 914                                         pdb_get_domain(conn->server_info->sam_account),
 915                                         lp_rootpreexec(snum));
 916                 DEBUG(5,("cmd=%s\n",cmd));
 917                 ret = smbrun(cmd,NULL);
 918                 TALLOC_FREE(cmd);
 919                 if (ret != 0 && lp_rootpreexec_close(snum)) {
 920                         DEBUG(1,("root preexec gave %d - failing "
 921                                  "connection\n", ret));
 922                         yield_connection(conn, lp_servicename(snum));
 923                         conn_free(conn);
 924                         *pstatus = NT_STATUS_ACCESS_DENIED;
 925                         return NULL;
 926                 }
 927         }
 928 
 929 /* USER Activites: */
 930         if (!change_to_user(conn, conn->vuid)) {
 931                 /* No point continuing if they fail the basic checks */
 932                 DEBUG(0,("Can't become connected user!\n"));
 933                 yield_connection(conn, lp_servicename(snum));
 934                 conn_free(conn);
 935                 *pstatus = NT_STATUS_LOGON_FAILURE;
 936                 return NULL;
 937         }
 938 
 939         /* Remember that a different vuid can connect later without these
 940          * checks... */
 941         
 942         /* Preexecs are done here as they might make the dir we are to ChDir
 943          * to below */
 944 
 945         /* execute any "preexec = " line */
 946         if (*lp_preexec(snum)) {
 947                 char *cmd = talloc_sub_advanced(talloc_tos(),
 948                                         lp_servicename(SNUM(conn)),
 949                                         conn->server_info->unix_name,
 950                                         conn->connectpath,
 951                                         conn->server_info->utok.gid,
 952                                         conn->server_info->sanitized_username,
 953                                         pdb_get_domain(conn->server_info->sam_account),
 954                                         lp_preexec(snum));
 955                 ret = smbrun(cmd,NULL);
 956                 TALLOC_FREE(cmd);
 957                 if (ret != 0 && lp_preexec_close(snum)) {
 958                         DEBUG(1,("preexec gave %d - failing connection\n",
 959                                  ret));
 960                         *pstatus = NT_STATUS_ACCESS_DENIED;
 961                         goto err_root_exit;
 962                 }
 963         }
 964 
 965 #ifdef WITH_FAKE_KASERVER
 966         if (lp_afs_share(snum)) {
 967                 afs_login(conn);
 968         }
 969 #endif
 970         
 971         /* Add veto/hide lists */
 972         if (!IS_IPC(conn) && !IS_PRINT(conn)) {
 973                 set_namearray( &conn->veto_list, lp_veto_files(snum));
 974                 set_namearray( &conn->hide_list, lp_hide_files(snum));
 975                 set_namearray( &conn->veto_oplock_list, lp_veto_oplocks(snum));
 976                 set_namearray( &conn->aio_write_behind_list,
 977                                 lp_aio_write_behind(snum));
 978         }
 979         
 980         /* Invoke VFS make connection hook - do this before the VFS_STAT call
 981            to allow any filesystems needing user credentials to initialize
 982            themselves. */
 983 
 984         if (SMB_VFS_CONNECT(conn, lp_servicename(snum),
 985                             conn->server_info->unix_name) < 0) {
 986                 DEBUG(0,("make_connection: VFS make connection failed!\n"));
 987                 *pstatus = NT_STATUS_UNSUCCESSFUL;
 988                 goto err_root_exit;
 989         }
 990 
 991         /* Any error exit after here needs to call the disconnect hook. */
 992         on_err_call_dis_hook = true;
 993 
 994         /* win2000 does not check the permissions on the directory
 995            during the tree connect, instead relying on permission
 996            check during individual operations. To match this behaviour
 997            I have disabled this chdir check (tridge) */
 998         /* the alternative is just to check the directory exists */
 999         if ((ret = SMB_VFS_STAT(conn, conn->connectpath, &st)) != 0 ||
1000             !S_ISDIR(st.st_mode)) {
1001                 if (ret == 0 && !S_ISDIR(st.st_mode)) {
1002                         DEBUG(0,("'%s' is not a directory, when connecting to "
1003                                  "[%s]\n", conn->connectpath,
1004                                  lp_servicename(snum)));
1005                 } else {
1006                         DEBUG(0,("'%s' does not exist or permission denied "
1007                                  "when connecting to [%s] Error was %s\n",
1008                                  conn->connectpath, lp_servicename(snum),
1009                                  strerror(errno) ));
1010                 }
1011                 *pstatus = NT_STATUS_BAD_NETWORK_NAME;
1012                 goto err_root_exit;
1013         }
1014 
1015         string_set(&conn->origpath,conn->connectpath);
1016 
1017 #if SOFTLINK_OPTIMISATION
1018         /* resolve any soft links early if possible */
1019         if (vfs_ChDir(conn,conn->connectpath) == 0) {
1020                 TALLOC_CTX *ctx = talloc_tos();
1021                 char *s = vfs_GetWd(ctx,s);
1022                 if (!s) {
1023                         *status = map_nt_error_from_unix(errno);
1024                         goto err_root_exit;
1025                 }
1026                 if (!set_conn_connectpath(conn,s)) {
1027                         *status = NT_STATUS_NO_MEMORY;
1028                         goto err_root_exit;
1029                 }
1030                 vfs_ChDir(conn,conn->connectpath);
1031         }
1032 #endif
1033 
1034         if (lp_unix_extensions() && lp_widelinks(snum)) {
1035                 DEBUG(0,("Share '%s' has wide links and unix extensions enabled. "
1036                         "These parameters are incompatible. "
1037                         "Disabling wide links for this share.\n",
1038                         lp_servicename(snum) ));
1039                 lp_do_parameter(snum, "wide links", "False");
1040         }
1041 
1042         /* Figure out the characteristics of the underlying filesystem. This
1043          * assumes that all the filesystem mounted withing a share path have
1044          * the same characteristics, which is likely but not guaranteed.
1045          */
1046 
1047         conn->fs_capabilities = SMB_VFS_FS_CAPABILITIES(conn);
1048 
1049         /*
1050          * Print out the 'connected as' stuff here as we need
1051          * to know the effective uid and gid we will be using
1052          * (at least initially).
1053          */
1054 
1055         if( DEBUGLVL( IS_IPC(conn) ? 3 : 1 ) ) {
1056                 dbgtext( "%s (%s) ", get_remote_machine_name(),
1057                          conn->client_address );
1058                 dbgtext( "%s", srv_is_signing_active() ? "signed " : "");
1059                 dbgtext( "connect to service %s ", lp_servicename(snum) );
1060                 dbgtext( "initially as user %s ",
1061                          conn->server_info->unix_name );
1062                 dbgtext( "(uid=%d, gid=%d) ", (int)geteuid(), (int)getegid() );
1063                 dbgtext( "(pid %d)\n", (int)sys_getpid() );
1064         }
1065 
1066         /* we've finished with the user stuff - go back to root */
1067         change_to_root_user();
1068         return(conn);
1069 
1070   err_root_exit:
1071 
1072         change_to_root_user();
1073         if (on_err_call_dis_hook) {
1074                 /* Call VFS disconnect hook */
1075                 SMB_VFS_DISCONNECT(conn);
1076         }
1077         yield_connection(conn, lp_servicename(snum));
1078         conn_free(conn);
1079         return NULL;
1080 }
1081 
1082 /****************************************************************************
1083  Make a connection to a service.
1084  *
1085  * @param service 
1086 ****************************************************************************/
1087 
1088 connection_struct *make_connection(const char *service_in, DATA_BLOB password, 
     /* [<][>][^][v][top][bottom][index][help] */
1089                                    const char *pdev, uint16 vuid,
1090                                    NTSTATUS *status)
1091 {
1092         uid_t euid;
1093         user_struct *vuser = NULL;
1094         fstring service;
1095         fstring dev;
1096         int snum = -1;
1097         char addr[INET6_ADDRSTRLEN];
1098 
1099         fstrcpy(dev, pdev);
1100 
1101         /* This must ONLY BE CALLED AS ROOT. As it exits this function as
1102          * root. */
1103         if (!non_root_mode() && (euid = geteuid()) != 0) {
1104                 DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot "
1105                          "(%u)\n", (unsigned int)euid ));
1106                 smb_panic("make_connection: PANIC ERROR. Called as nonroot\n");
1107         }
1108 
1109         if (conn_num_open() > 2047) {
1110                 *status = NT_STATUS_INSUFF_SERVER_RESOURCES;
1111                 return NULL;
1112         }
1113 
1114         if(lp_security() != SEC_SHARE) {
1115                 vuser = get_valid_user_struct(vuid);
1116                 if (!vuser) {
1117                         DEBUG(1,("make_connection: refusing to connect with "
1118                                  "no session setup\n"));
1119                         *status = NT_STATUS_ACCESS_DENIED;
1120                         return NULL;
1121                 }
1122         }
1123 
1124         /* Logic to try and connect to the correct [homes] share, preferably
1125            without too many getpwnam() lookups.  This is particulary nasty for
1126            winbind usernames, where the share name isn't the same as unix
1127            username.
1128 
1129            The snum of the homes share is stored on the vuser at session setup
1130            time.
1131         */
1132 
1133         if (strequal(service_in,HOMES_NAME)) {
1134                 if(lp_security() != SEC_SHARE) {
1135                         DATA_BLOB no_pw = data_blob_null;
1136                         if (vuser->homes_snum == -1) {
1137                                 DEBUG(2, ("[homes] share not available for "
1138                                           "this user because it was not found "
1139                                           "or created at session setup "
1140                                           "time\n"));
1141                                 *status = NT_STATUS_BAD_NETWORK_NAME;
1142                                 return NULL;
1143                         }
1144                         DEBUG(5, ("making a connection to [homes] service "
1145                                   "created at session setup time\n"));
1146                         return make_connection_snum(vuser->homes_snum,
1147                                                     vuser, no_pw, 
1148                                                     dev, status);
1149                 } else {
1150                         /* Security = share. Try with
1151                          * current_user_info.smb_name as the username.  */
1152                         if (*current_user_info.smb_name) {
1153                                 fstring unix_username;
1154                                 fstrcpy(unix_username,
1155                                         current_user_info.smb_name);
1156                                 map_username(unix_username);
1157                                 snum = find_service(unix_username);
1158                         } 
1159                         if (snum != -1) {
1160                                 DEBUG(5, ("making a connection to 'homes' "
1161                                           "service %s based on "
1162                                           "security=share\n", service_in));
1163                                 return make_connection_snum(snum, NULL,
1164                                                             password,
1165                                                             dev, status);
1166                         }
1167                 }
1168         } else if ((lp_security() != SEC_SHARE) && (vuser->homes_snum != -1)
1169                    && strequal(service_in,
1170                                lp_servicename(vuser->homes_snum))) {
1171                 DATA_BLOB no_pw = data_blob_null;
1172                 DEBUG(5, ("making a connection to 'homes' service [%s] "
1173                           "created at session setup time\n", service_in));
1174                 return make_connection_snum(vuser->homes_snum,
1175                                             vuser, no_pw, 
1176                                             dev, status);
1177         }
1178         
1179         fstrcpy(service, service_in);
1180 
1181         strlower_m(service);
1182 
1183         snum = find_service(service);
1184 
1185         if (snum < 0) {
1186                 if (strequal(service,"IPC$") ||
1187                     (lp_enable_asu_support() && strequal(service,"ADMIN$"))) {
1188                         DEBUG(3,("refusing IPC connection to %s\n", service));
1189                         *status = NT_STATUS_ACCESS_DENIED;
1190                         return NULL;
1191                 }
1192 
1193                 DEBUG(0,("%s (%s) couldn't find service %s\n",
1194                         get_remote_machine_name(),
1195                         client_addr(get_client_fd(),addr,sizeof(addr)),
1196                         service));
1197                 *status = NT_STATUS_BAD_NETWORK_NAME;
1198                 return NULL;
1199         }
1200 
1201         /* Handle non-Dfs clients attempting connections to msdfs proxy */
1202         if (lp_host_msdfs() && (*lp_msdfs_proxy(snum) != '\0'))  {
1203                 DEBUG(3, ("refusing connection to dfs proxy share '%s' "
1204                           "(pointing to %s)\n", 
1205                         service, lp_msdfs_proxy(snum)));
1206                 *status = NT_STATUS_BAD_NETWORK_NAME;
1207                 return NULL;
1208         }
1209 
1210         DEBUG(5, ("making a connection to 'normal' service %s\n", service));
1211 
1212         return make_connection_snum(snum, vuser,
1213                                     password,
1214                                     dev, status);
1215 }
1216 
1217 /****************************************************************************
1218  Close a cnum.
1219 ****************************************************************************/
1220 
1221 void close_cnum(connection_struct *conn, uint16 vuid)
     /* [<][>][^][v][top][bottom][index][help] */
1222 {
1223         file_close_conn(conn);
1224 
1225         if (!IS_IPC(conn)) {
1226                 dptr_closecnum(conn);
1227         }
1228 
1229         change_to_root_user();
1230 
1231         DEBUG(IS_IPC(conn)?3:1, ("%s (%s) closed connection to service %s\n",
1232                                  get_remote_machine_name(),
1233                                  conn->client_address,
1234                                  lp_servicename(SNUM(conn))));
1235 
1236         /* Call VFS disconnect hook */    
1237         SMB_VFS_DISCONNECT(conn);
1238 
1239         yield_connection(conn, lp_servicename(SNUM(conn)));
1240 
1241         /* make sure we leave the directory available for unmount */
1242         vfs_ChDir(conn, "/");
1243 
1244         /* execute any "postexec = " line */
1245         if (*lp_postexec(SNUM(conn)) && 
1246             change_to_user(conn, vuid))  {
1247                 char *cmd = talloc_sub_advanced(talloc_tos(),
1248                                         lp_servicename(SNUM(conn)),
1249                                         conn->server_info->unix_name,
1250                                         conn->connectpath,
1251                                         conn->server_info->utok.gid,
1252                                         conn->server_info->sanitized_username,
1253                                         pdb_get_domain(conn->server_info->sam_account),
1254                                         lp_postexec(SNUM(conn)));
1255                 smbrun(cmd,NULL);
1256                 TALLOC_FREE(cmd);
1257                 change_to_root_user();
1258         }
1259 
1260         change_to_root_user();
1261         /* execute any "root postexec = " line */
1262         if (*lp_rootpostexec(SNUM(conn)))  {
1263                 char *cmd = talloc_sub_advanced(talloc_tos(),
1264                                         lp_servicename(SNUM(conn)),
1265                                         conn->server_info->unix_name,
1266                                         conn->connectpath,
1267                                         conn->server_info->utok.gid,
1268                                         conn->server_info->sanitized_username,
1269                                         pdb_get_domain(conn->server_info->sam_account),
1270                                         lp_rootpostexec(SNUM(conn)));
1271                 smbrun(cmd,NULL);
1272                 TALLOC_FREE(cmd);
1273         }
1274 
1275         conn_free(conn);
1276 }

/* [<][>][^][v][top][bottom][index][help] */