Print this page
4078 groupadd execs getent unnecessarily
Reviewed by: Rich Lowe <richlowe@richlowe.net>
Reviewed by: Gary Mills <gary_mills@fastmail.fm>
Reviewed by: Milan Jurik <milan.jurik@xylab.cz>
Reviewed by: Gordon Ross <Gordon.W.Ross@gmail.com>


   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  24  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.

  25  */
  26 
  27 #include <stdlib.h>
  28 #include <strings.h>
  29 #include <unistd.h>
  30 #include <syslog.h>
  31 #include <thread.h>
  32 #include <synch.h>
  33 #include <grp.h>
  34 #include <assert.h>
  35 #include <libintl.h>
  36 #include <smbsrv/libsmb.h>
  37 #include <smb_sqlite.h>
  38 #include <sys/types.h>
  39 #include <sys/stat.h>
  40 #include <sys/param.h>

  41 
  42 /*
  43  * Local domain SID (aka machine SID) is not stored in the domain table
  44  * therefore the index is 0
  45  */
  46 #define SMB_LGRP_LOCAL_IDX      0
  47 #define SMB_LGRP_BUILTIN_IDX    1
  48 
  49 #define SMB_LGRP_DB_NAME        "/var/smb/smbgroup.db"
  50 #define SMB_LGRP_DB_TIMEOUT     3000            /* in millisecond */
  51 #define SMB_LGRP_DB_VERMAJOR    1
  52 #define SMB_LGRP_DB_VERMINOR    0
  53 #define SMB_LGRP_DB_MAGIC       0x4C475250      /* LGRP */
  54 
  55 #define SMB_LGRP_DB_ORD         1               /* open read-only */
  56 #define SMB_LGRP_DB_ORW         2               /* open read/write */
  57 
  58 #define SMB_LGRP_DB_ADDMEMBER   1
  59 #define SMB_LGRP_DB_DELMEMBER   2
  60 


 106 #define SMB_LGRP_GTBL_SIDTYP    3
 107 #define SMB_LGRP_GTBL_SIDATR    4
 108 #define SMB_LGRP_GTBL_CMNT      5
 109 #define SMB_LGRP_GTBL_NPRIVS    6
 110 #define SMB_LGRP_GTBL_PRIVS     7
 111 #define SMB_LGRP_GTBL_NMEMBS    8
 112 #define SMB_LGRP_GTBL_MEMBS     9
 113 
 114 #define SMB_LGRP_INFO_NONE      0x00
 115 #define SMB_LGRP_INFO_NAME      0x01
 116 #define SMB_LGRP_INFO_CMNT      0x02
 117 #define SMB_LGRP_INFO_SID       0x04
 118 #define SMB_LGRP_INFO_PRIV      0x08
 119 #define SMB_LGRP_INFO_MEMB      0x10
 120 #define SMB_LGRP_INFO_ALL       0x1F
 121 
 122 #define SMB_LGRP_PGRP_GRPTMP    "/etc/gtmp"
 123 #define SMB_LGRP_PGRP_GRPBUFSIZ 5120
 124 #define SMB_LGRP_PGRP_GROUP     "/etc/group"
 125 #define SMB_LGRP_PGRP_MAXGLEN   9       /* max length of group name */
 126 #define SMB_LGRP_PGRP_DEFRID    99      /* max reserved id */
 127 
 128 #define SMB_LGRP_PGRP_NOTUNIQUE 0
 129 #define SMB_LGRP_PGRP_RESERVED  1
 130 #define SMB_LGRP_PGRP_UNIQUE    2
 131 #define SMB_LGRP_PGRP_TOOBIG    3
 132 #define SMB_LGRP_PGRP_INVALID   4
 133 
 134 #define NULL_MSGCHK(msg)        ((msg) ? (msg) : "NULL")
 135 
 136 /* Member ID */
 137 typedef struct smb_lgmid {
 138         uint32_t m_idx;
 139         uint32_t m_rid;
 140         uint16_t m_type;
 141 } smb_lgmid_t;
 142 
 143 #define SMB_LGRP_MID_HEXSZ      32
 144 
 145 /* Member list */
 146 typedef struct smb_lgmlist {


2528 
2529         for (c = *ptr; c != NULL; ptr++, c = *ptr) {
2530                 len++;
2531                 if (!isprint(c) || (c == ':') || (c == '\n'))
2532                         return (SMB_LGRP_PGRP_INVALID);
2533 
2534                 if (!(islower(c) || isdigit(c)))
2535                         badchar++;
2536         }
2537 
2538         if ((len > SMB_LGRP_PGRP_MAXGLEN - 1) || (badchar != 0))
2539                 return (SMB_LGRP_PGRP_INVALID);
2540 
2541         if (getgrnam(group) != NULL)
2542                 return (SMB_LGRP_PGRP_NOTUNIQUE);
2543 
2544         return (SMB_LGRP_PGRP_UNIQUE);
2545 }
2546 
2547 /*
2548  * smb_lgrp_pgrp_valid_gid
2549  *
2550  * Check to see that the gid is not a reserved gid
2551  * -- nobody (60001), noaccess (60002) or nogroup (65534)
2552  */
2553 static int
2554 smb_lgrp_pgrp_valid_gid(gid_t gid)
2555 {
2556         return (gid != 60001 && gid != 60002 && gid != 65534);
2557 }
2558 
2559 /*
2560  * smb_lgrp_pgrp_findnextgid(void)
2561  *
2562  * This method finds the next valid GID.
2563  * It sorts the used GIDs in decreasing order to return MAXUSED + 1.
2564  * It then adds one to obtain the next valid GID.
2565  * On failure, -1 is returned. On success, a valid GID is returned.
2566  */
2567 static int
2568 smb_lgrp_pgrp_findnextgid(void)
2569 {
2570         FILE *fptr;
2571         gid_t last, next;
2572         int gid;
2573 
2574         if ((fptr = popen("exec sh -c "
2575             "\"getent group|cut -f3 -d:|sort -nr|uniq \" 2>/dev/null",
2576             "r")) == NULL)
2577                 return (-1);
2578 
2579         if (fscanf(fptr, "%u\n", &next) == EOF) {
2580                 (void) pclose(fptr);
2581                 return (SMB_LGRP_PGRP_DEFRID + 1);
2582         }
2583 
2584         last = MAXUID;
2585         gid = -1;
2586         do {
2587                 if (!smb_lgrp_pgrp_valid_gid(next))
2588                         continue;
2589 
2590                 if (next <= SMB_LGRP_PGRP_DEFRID) {
2591                         if (last != SMB_LGRP_PGRP_DEFRID + 1)
2592                                 gid = SMB_LGRP_PGRP_DEFRID + 1;
2593                         break;
2594                 }
2595 
2596                 if ((gid = next + 1) != last) {
2597                         while (!smb_lgrp_pgrp_valid_gid((gid_t)gid))
2598                                 gid++;
2599                         if (gid > 0 && gid < last)
2600                                 break;
2601                 }
2602 
2603                 gid = -1;
2604                 last = next;
2605         } while (fscanf(fptr, "%u\n", &next) != EOF);
2606 
2607         (void) pclose(fptr);
2608         return (gid);
2609 }
2610 
2611 /*
2612  * smb_lgrp_pgrp_add
2613  *
2614  * Create a posix group with the given name.
2615  * This group will be added to the /etc/group file.
2616  */
2617 static int
2618 smb_lgrp_pgrp_add(char *group)
2619 {
2620         FILE *etcgrp;
2621         FILE *etctmp;
2622         int o_mask, gret;
2623         int newdone = 0;
2624         struct stat sb;
2625         char buf[SMB_LGRP_PGRP_GRPBUFSIZ];
2626         gid_t gid;
2627         int rc = 0;
2628 
2629         rc = smb_lgrp_pgrp_valid_gname(group);
2630         if ((rc == SMB_LGRP_PGRP_INVALID) || (rc == SMB_LGRP_PGRP_NOTUNIQUE))
2631                 return (-1);
2632 
2633         if ((gret = smb_lgrp_pgrp_findnextgid()) < 0)
2634                 return (-1);
2635         gid = gret;
2636 
2637         if ((etcgrp = fopen(SMB_LGRP_PGRP_GROUP, "r")) == NULL)
2638                 return (-1);
2639 
2640         if (fstat(fileno(etcgrp), &sb) < 0)
2641                 sb.st_mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH;
2642 
2643         o_mask = umask(077);
2644         etctmp = fopen(SMB_LGRP_PGRP_GRPTMP, "w+");
2645         (void) umask(o_mask);
2646 
2647         if (etctmp == NULL) {
2648                 (void) fclose(etcgrp);
2649                 return (-1);
2650         }
2651 
2652         if (lockf(fileno(etctmp), F_LOCK, 0) != 0) {
2653                 (void) fclose(etcgrp);
2654                 (void) fclose(etctmp);
2655                 (void) unlink(SMB_LGRP_PGRP_GRPTMP);




   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  24  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
  25  * Copyright (c) 2013 RackTop Systems.
  26  */
  27 
  28 #include <stdlib.h>
  29 #include <strings.h>
  30 #include <unistd.h>
  31 #include <syslog.h>
  32 #include <thread.h>
  33 #include <synch.h>
  34 #include <grp.h>
  35 #include <assert.h>
  36 #include <libintl.h>
  37 #include <smbsrv/libsmb.h>
  38 #include <smb_sqlite.h>
  39 #include <sys/types.h>
  40 #include <sys/stat.h>
  41 #include <sys/param.h>
  42 #include <libcmdutils.h>
  43 
  44 /*
  45  * Local domain SID (aka machine SID) is not stored in the domain table
  46  * therefore the index is 0
  47  */
  48 #define SMB_LGRP_LOCAL_IDX      0
  49 #define SMB_LGRP_BUILTIN_IDX    1
  50 
  51 #define SMB_LGRP_DB_NAME        "/var/smb/smbgroup.db"
  52 #define SMB_LGRP_DB_TIMEOUT     3000            /* in millisecond */
  53 #define SMB_LGRP_DB_VERMAJOR    1
  54 #define SMB_LGRP_DB_VERMINOR    0
  55 #define SMB_LGRP_DB_MAGIC       0x4C475250      /* LGRP */
  56 
  57 #define SMB_LGRP_DB_ORD         1               /* open read-only */
  58 #define SMB_LGRP_DB_ORW         2               /* open read/write */
  59 
  60 #define SMB_LGRP_DB_ADDMEMBER   1
  61 #define SMB_LGRP_DB_DELMEMBER   2
  62 


 108 #define SMB_LGRP_GTBL_SIDTYP    3
 109 #define SMB_LGRP_GTBL_SIDATR    4
 110 #define SMB_LGRP_GTBL_CMNT      5
 111 #define SMB_LGRP_GTBL_NPRIVS    6
 112 #define SMB_LGRP_GTBL_PRIVS     7
 113 #define SMB_LGRP_GTBL_NMEMBS    8
 114 #define SMB_LGRP_GTBL_MEMBS     9
 115 
 116 #define SMB_LGRP_INFO_NONE      0x00
 117 #define SMB_LGRP_INFO_NAME      0x01
 118 #define SMB_LGRP_INFO_CMNT      0x02
 119 #define SMB_LGRP_INFO_SID       0x04
 120 #define SMB_LGRP_INFO_PRIV      0x08
 121 #define SMB_LGRP_INFO_MEMB      0x10
 122 #define SMB_LGRP_INFO_ALL       0x1F
 123 
 124 #define SMB_LGRP_PGRP_GRPTMP    "/etc/gtmp"
 125 #define SMB_LGRP_PGRP_GRPBUFSIZ 5120
 126 #define SMB_LGRP_PGRP_GROUP     "/etc/group"
 127 #define SMB_LGRP_PGRP_MAXGLEN   9       /* max length of group name */
 128 #define SMB_LGRP_PGRP_DEFRID    1000    /* lowest cifs created gid */
 129 
 130 #define SMB_LGRP_PGRP_NOTUNIQUE 0
 131 #define SMB_LGRP_PGRP_RESERVED  1
 132 #define SMB_LGRP_PGRP_UNIQUE    2
 133 #define SMB_LGRP_PGRP_TOOBIG    3
 134 #define SMB_LGRP_PGRP_INVALID   4
 135 
 136 #define NULL_MSGCHK(msg)        ((msg) ? (msg) : "NULL")
 137 
 138 /* Member ID */
 139 typedef struct smb_lgmid {
 140         uint32_t m_idx;
 141         uint32_t m_rid;
 142         uint16_t m_type;
 143 } smb_lgmid_t;
 144 
 145 #define SMB_LGRP_MID_HEXSZ      32
 146 
 147 /* Member list */
 148 typedef struct smb_lgmlist {


2530 
2531         for (c = *ptr; c != NULL; ptr++, c = *ptr) {
2532                 len++;
2533                 if (!isprint(c) || (c == ':') || (c == '\n'))
2534                         return (SMB_LGRP_PGRP_INVALID);
2535 
2536                 if (!(islower(c) || isdigit(c)))
2537                         badchar++;
2538         }
2539 
2540         if ((len > SMB_LGRP_PGRP_MAXGLEN - 1) || (badchar != 0))
2541                 return (SMB_LGRP_PGRP_INVALID);
2542 
2543         if (getgrnam(group) != NULL)
2544                 return (SMB_LGRP_PGRP_NOTUNIQUE);
2545 
2546         return (SMB_LGRP_PGRP_UNIQUE);
2547 }
2548 
2549 /*
































































2550  * smb_lgrp_pgrp_add
2551  *
2552  * Create a posix group with the given name.
2553  * This group will be added to the /etc/group file.
2554  */
2555 static int
2556 smb_lgrp_pgrp_add(char *group)
2557 {
2558         FILE *etcgrp;
2559         FILE *etctmp;
2560         int o_mask;
2561         int newdone = 0;
2562         struct stat sb;
2563         char buf[SMB_LGRP_PGRP_GRPBUFSIZ];
2564         gid_t gid;
2565         int rc = 0;
2566 
2567         rc = smb_lgrp_pgrp_valid_gname(group);
2568         if ((rc == SMB_LGRP_PGRP_INVALID) || (rc == SMB_LGRP_PGRP_NOTUNIQUE))
2569                 return (-1);
2570 
2571         if ((findnextgid(SMB_LGRP_PGRP_DEFRID, MAXUID, &gid)) != 0)
2572                 return (-1);

2573 
2574         if ((etcgrp = fopen(SMB_LGRP_PGRP_GROUP, "r")) == NULL)
2575                 return (-1);
2576 
2577         if (fstat(fileno(etcgrp), &sb) < 0)
2578                 sb.st_mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH;
2579 
2580         o_mask = umask(077);
2581         etctmp = fopen(SMB_LGRP_PGRP_GRPTMP, "w+");
2582         (void) umask(o_mask);
2583 
2584         if (etctmp == NULL) {
2585                 (void) fclose(etcgrp);
2586                 return (-1);
2587         }
2588 
2589         if (lockf(fileno(etctmp), F_LOCK, 0) != 0) {
2590                 (void) fclose(etcgrp);
2591                 (void) fclose(etctmp);
2592                 (void) unlink(SMB_LGRP_PGRP_GRPTMP);