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>
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/cmd/oamuser/user/funcs.c
          +++ new/usr/src/cmd/oamuser/user/funcs.c
   1    1  /*
   2    2   * CDDL HEADER START
   3    3   *
   4    4   * The contents of this file are subject to the terms of the
   5    5   * Common Development and Distribution License (the "License").
   6    6   * You may not use this file except in compliance with the License.
   7    7   *
   8    8   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9    9   * or http://www.opensolaris.org/os/licensing.
  10   10   * See the License for the specific language governing permissions
  11   11   * and limitations under the License.
  12   12   *
  
    | 
      ↓ open down ↓ | 
    12 lines elided | 
    
      ↑ open up ↑ | 
  
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
  22   22   * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
       23 + * Copyright (c) 2013 RackTop Systems.
  23   24   */
  24   25  
  25   26  #include <stdio.h>
  26   27  #include <stdlib.h>
  27   28  #include <strings.h>
  28   29  #include <auth_attr.h>
  29   30  #include <prof_attr.h>
  30   31  #include <user_attr.h>
  31   32  #include <project.h>
  32   33  #include <secdb.h>
  33   34  #include <pwd.h>
  34   35  #include <unistd.h>
  35   36  #include <priv.h>
  36   37  #include <errno.h>
  37   38  #include <ctype.h>
  38   39  #include <nss.h>
  39   40  #include <bsm/libbsm.h>
  40   41  #include <tsol/label.h>
  41   42  #include "funcs.h"
  42   43  #include "messages.h"
  43   44  #undef  GROUP
  44   45  #include "userdefs.h"
  45   46  
  46   47  typedef struct ua_key {
  47   48          const char      *key;
  48   49          const char      *(*check)(const char *);
  49   50          const char      *errstr;
  50   51          char            *newvalue;
  51   52  } ua_key_t;
  52   53  
  53   54  static const char role[] = "role name";
  54   55  static const char prof[] = "profile name";
  55   56  static const char proj[] = "project name";
  56   57  static const char priv[] = "privilege set";
  57   58  static const char auth[] = "authorization";
  58   59  static const char type[] = "user type";
  59   60  static const char lock[] = "lock_after_retries value";
  60   61  static const char label[] = "label";
  61   62  static const char idlecmd[] = "idlecmd value";
  62   63  static const char idletime[] = "idletime value";
  63   64  static const char auditflags[] = "audit mask";
  64   65  static char       auditerr[256];
  65   66  
  66   67  
  67   68  static const char *check_auth(const char *);
  68   69  static const char *check_prof(const char *);
  69   70  static const char *check_role(const char *);
  70   71  static const char *check_proj(const char *);
  71   72  static const char *check_privset(const char *);
  72   73  static const char *check_type(const char *);
  73   74  static const char *check_lock_after_retries(const char *);
  74   75  static const char *check_label(const char *);
  75   76  static const char *check_idlecmd(const char *);
  76   77  static const char *check_idletime(const char *);
  77   78  static const char *check_auditflags(const char *);
  78   79  
  79   80  int nkeys;
  80   81  
  81   82  static ua_key_t keys[] = {
  82   83          /* First entry is always set correctly in main() */
  83   84          { USERATTR_TYPE_KW,     check_type,     type },
  84   85          { USERATTR_AUTHS_KW,    check_auth,     auth },
  85   86          { USERATTR_PROFILES_KW, check_prof,     prof },
  86   87          { USERATTR_ROLES_KW,    check_role,     role },
  87   88          { USERATTR_DEFAULTPROJ_KW,      check_proj,     proj },
  88   89          { USERATTR_LIMPRIV_KW,  check_privset,  priv },
  89   90          { USERATTR_DFLTPRIV_KW, check_privset,  priv },
  90   91          { USERATTR_LOCK_AFTER_RETRIES_KW, check_lock_after_retries,  lock },
  91   92          { USERATTR_CLEARANCE,   check_label,    label },
  92   93          { USERATTR_MINLABEL,    check_label,    label },
  93   94          { USERATTR_IDLECMD_KW,  check_idlecmd,  idlecmd },
  94   95          { USERATTR_IDLETIME_KW, check_idletime, idletime },
  95   96          { USERATTR_AUDIT_FLAGS_KW, check_auditflags, auditflags },
  96   97  };
  97   98  
  98   99  #define NKEYS   (sizeof (keys)/sizeof (ua_key_t))
  99  100  
 100  101  /*
 101  102   * Change a key, there are three different call sequences:
 102  103   *
 103  104   *              key, value      - key with option letter, value.
 104  105   *              NULL, value     - -K key=value option.
 105  106   */
 106  107  
 107  108  void
 108  109  change_key(const char *key, char *value)
 109  110  {
 110  111          int i;
 111  112          const char *res;
 112  113  
 113  114          if (key == NULL) {
 114  115                  key = value;
 115  116                  value = strchr(value, '=');
 116  117                  /* Bad value */
 117  118                  if (value == NULL) {
 118  119                          errmsg(M_INVALID_VALUE);
 119  120                          exit(EX_BADARG);
 120  121                  }
 121  122                  *value++ = '\0';
 122  123          }
 123  124  
 124  125          for (i = 0; i < NKEYS; i++) {
 125  126                  if (strcmp(key, keys[i].key) == 0) {
 126  127                          if (keys[i].newvalue != NULL) {
 127  128                                  /* Can't set a value twice */
 128  129                                  errmsg(M_REDEFINED_KEY, key);
 129  130                                  exit(EX_BADARG);
 130  131                          }
 131  132  
 132  133                          if (keys[i].check != NULL &&
 133  134                              (res = keys[i].check(value)) != NULL) {
 134  135                                  errmsg(M_INVALID, res, keys[i].errstr);
 135  136                                  exit(EX_BADARG);
 136  137                          }
 137  138                          keys[i].newvalue = value;
 138  139                          nkeys++;
 139  140                          return;
 140  141                  }
 141  142          }
 142  143          errmsg(M_INVALID_KEY, key);
 143  144          exit(EX_BADARG);
 144  145  }
 145  146  
 146  147  /*
 147  148   * Add the keys to the argument vector.
 148  149   */
 149  150  void
 150  151  addkey_args(char **argv, int *index)
 151  152  {
 152  153          int i;
 153  154  
 154  155          for (i = 0; i < NKEYS; i++) {
 155  156                  const char *key = keys[i].key;
 156  157                  char *val = keys[i].newvalue;
 157  158                  size_t len;
 158  159                  char *arg;
 159  160  
 160  161                  if (val == NULL)
 161  162                          continue;
 162  163  
 163  164                  len = strlen(key) + strlen(val) + 2;
 164  165                  arg = malloc(len);
 165  166  
 166  167                  (void) snprintf(arg, len, "%s=%s", key, val);
 167  168                  argv[(*index)++] = "-K";
 168  169                  argv[(*index)++] = arg;
 169  170          }
 170  171  }
 171  172  
 172  173  /*
  
    | 
      ↓ open down ↓ | 
    140 lines elided | 
    
      ↑ open up ↑ | 
  
 173  174   * Propose a default value for a key and get the actual value back.
 174  175   * If the proposed default value is NULL, return the actual value set.
 175  176   * The key argument is the user_attr key.
 176  177   */
 177  178  char *
 178  179  getsetdefval(const char *key, char *dflt)
 179  180  {
 180  181          int i;
 181  182  
 182  183          for (i = 0; i < NKEYS; i++)
 183      -                if (strcmp(keys[i].key, key) == 0)
      184 +                if (strcmp(keys[i].key, key) == 0) {
 184  185                          if (keys[i].newvalue != NULL)
 185  186                                  return (keys[i].newvalue);
 186  187                          else
 187  188                                  return (keys[i].newvalue = dflt);
      189 +                }
 188  190          return (NULL);
 189  191  }
 190  192  
 191  193  char *
 192  194  getusertype(char *cmdname)
 193  195  {
 194  196          static char usertype[MAX_TYPE_LENGTH];
 195  197          char *cmd;
 196  198  
 197      -        if (cmd = strrchr(cmdname, '/'))
      199 +        if ((cmd = strrchr(cmdname, '/')))
 198  200                  ++cmd;
 199  201          else
 200  202                  cmd = cmdname;
 201  203  
 202  204          /* get user type based on the program name */
 203  205          if (strncmp(cmd, CMD_PREFIX_USER,
 204  206              strlen(CMD_PREFIX_USER)) == 0)
 205  207                  strcpy(usertype, USERATTR_TYPE_NORMAL_KW);
 206  208          else
 207  209                  strcpy(usertype, USERATTR_TYPE_NONADMIN_KW);
 208  210  
 209  211          return (usertype);
 210  212  }
 211  213  
 212  214  int
 213  215  is_role(char *usertype)
 214  216  {
 215  217          if (strcmp(usertype, USERATTR_TYPE_NONADMIN_KW) == 0)
 216  218                  return (1);
 217  219          /* not a role */
 218  220          return (0);
 219  221  }
 220  222  
 221  223  /*
 222  224   * Verifies the provided list of authorizations are all valid.
 223  225   *
 224  226   * Returns NULL if all authorization names are valid.
 225  227   * Otherwise, returns the invalid authorization name
 226  228   *
 227  229   */
 228  230  static const char *
 229  231  check_auth(const char *auths)
 230  232  {
 231  233          char *authname;
 232  234          authattr_t *result;
 233  235          char *tmp;
 234  236          struct passwd   *pw;
 235  237          int have_grant = 0;
 236  238  
 237  239          tmp = strdup(auths);
 238  240          if (tmp == NULL) {
 239  241                  errmsg(M_NOSPACE);
 240  242                  exit(EX_FAILURE);
 241  243          }
 242  244  
 243  245          authname = strtok(tmp, AUTH_SEP);
 244  246          pw = getpwuid(getuid());
 245  247          if (pw == NULL) {
 246  248                  return (authname);
 247  249          }
 248  250  
 249  251          while (authname != NULL) {
 250  252                  char *suffix;
 251  253                  char *authtoks;
 252  254  
 253  255                  /* Check if user has been granted this authorization */
 254  256                  if (!chkauthattr(authname, pw->pw_name))
 255  257                          return (authname);
 256  258  
 257  259                  /* Remove named object after slash */
 258  260                  if ((suffix = index(authname, KV_OBJECTCHAR)) != NULL)
 259  261                          *suffix = '\0';
 260  262  
 261  263                  /* Find the suffix */
 262  264                  if ((suffix = rindex(authname, '.')) == NULL)
 263  265                          return (authname);
 264  266  
 265  267                  /* Check for existence in auth_attr */
 266  268                  suffix++;
 267  269                  if (strcmp(suffix, KV_WILDCARD)) { /* Not a wildcard */
 268  270                          result = getauthnam(authname);
 269  271                          if (result == NULL) {
 270  272                          /* can't find the auth */
 271  273                                  free_authattr(result);
 272  274                                  return (authname);
 273  275                          }
 274  276                          free_authattr(result);
 275  277                  }
 276  278  
 277  279                  /* Check if user can delegate this authorization */
 278  280                  if (strcmp(suffix, "grant")) { /* Not a grant option */
 279  281                          authtoks = malloc(strlen(authname) + sizeof ("grant"));
 280  282                          strcpy(authtoks, authname);
 281  283                          have_grant = 0;
 282  284                          while ((suffix = rindex(authtoks, '.')) &&
 283  285                              !have_grant) {
 284  286                                  strcpy(suffix, ".grant");
 285  287                                  if (chkauthattr(authtoks, pw->pw_name))
 286  288                                          have_grant = 1;
 287  289                                  else
 288  290                                          *suffix = '\0';
 289  291                          }
 290  292                          if (!have_grant)
 291  293                                  return (authname);
 292  294                  }
 293  295                  authname = strtok(NULL, AUTH_SEP);
 294  296          }
 295  297          free(tmp);
 296  298          return (NULL);
 297  299  }
 298  300  
 299  301  /*
 300  302   * Verifies the provided list of profile names are valid.
 301  303   *
 302  304   * Returns NULL if all profile names are valid.
 303  305   * Otherwise, returns the invalid profile name
 304  306   *
 305  307   */
 306  308  static const char *
 307  309  check_prof(const char *profs)
 308  310  {
 309  311          char *profname;
 310  312          profattr_t *result;
 311  313          char *tmp;
 312  314  
 313  315          tmp = strdup(profs);
 314  316          if (tmp == NULL) {
 315  317                  errmsg(M_NOSPACE);
 316  318                  exit(EX_FAILURE);
 317  319          }
 318  320  
 319  321          profname = strtok(tmp, PROF_SEP);
 320  322          while (profname != NULL) {
 321  323                  result = getprofnam(profname);
 322  324                  if (result == NULL) {
 323  325                  /* can't find the profile */
 324  326                          return (profname);
 325  327                  }
 326  328                  free_profattr(result);
 327  329                  profname = strtok(NULL, PROF_SEP);
 328  330          }
 329  331          free(tmp);
 330  332          return (NULL);
 331  333  }
 332  334  
 333  335  
 334  336  /*
 335  337   * Verifies the provided list of role names are valid.
 336  338   *
 337  339   * Returns NULL if all role names are valid.
 338  340   * Otherwise, returns the invalid role name
 339  341   *
 340  342   */
 341  343  static const char *
 342  344  check_role(const char *roles)
 343  345  {
 344  346          char *rolename;
 345  347          userattr_t *result;
 346  348          char *utype;
 347  349          char *tmp;
 348  350  
 349  351          tmp = strdup(roles);
 350  352          if (tmp == NULL) {
 351  353                  errmsg(M_NOSPACE);
 352  354                  exit(EX_FAILURE);
 353  355          }
 354  356  
 355  357          rolename = strtok(tmp, ROLE_SEP);
 356  358          while (rolename != NULL) {
 357  359                  result = getusernam(rolename);
 358  360                  if (result == NULL) {
 359  361                  /* can't find the rolename */
 360  362                          return (rolename);
 361  363                  }
 362  364                  /* Now, make sure it is a role */
 363  365                  utype = kva_match(result->attr, USERATTR_TYPE_KW);
 364  366                  if (utype == NULL) {
 365  367                          /* no user type defined. not a role */
 366  368                          free_userattr(result);
 367  369                          return (rolename);
 368  370                  }
 369  371                  if (strcmp(utype, USERATTR_TYPE_NONADMIN_KW) != 0) {
 370  372                          free_userattr(result);
 371  373                          return (rolename);
 372  374                  }
 373  375                  free_userattr(result);
 374  376                  rolename = strtok(NULL, ROLE_SEP);
 375  377          }
 376  378          free(tmp);
 377  379          return (NULL);
 378  380  }
 379  381  
 380  382  static const char *
 381  383  check_proj(const char *proj)
 382  384  {
 383  385          if (getprojidbyname(proj) < 0) {
 384  386                  return (proj);
 385  387          } else {
 386  388                  return (NULL);
 387  389          }
 388  390  }
 389  391  
 390  392  static const char *
 391  393  check_privset(const char *pset)
 392  394  {
 393  395          priv_set_t *tmp;
 394  396          const char *res;
 395  397  
 396  398          tmp = priv_str_to_set(pset, ",", &res);
 397  399  
 398  400          if (tmp != NULL) {
 399  401                  res = NULL;
 400  402                  priv_freeset(tmp);
 401  403          } else if (res == NULL)
 402  404                  res = strerror(errno);
 403  405  
 404  406          return (res);
 405  407  }
 406  408  
 407  409  static const char *
 408  410  check_type(const char *type)
 409  411  {
 410  412          if (strcmp(type, USERATTR_TYPE_NONADMIN_KW) != 0 &&
 411  413              strcmp(type, USERATTR_TYPE_NORMAL_KW) != 0)
 412  414                  return (type);
 413  415  
 414  416          return (NULL);
 415  417  }
 416  418  
 417  419  static const char *
 418  420  check_lock_after_retries(const char *keyval)
 419  421  {
 420  422          if (keyval != NULL) {
 421  423                  if ((strcasecmp(keyval, "no") != 0) &&
 422  424                      (strcasecmp(keyval, "yes") != 0) &&
 423  425                      (*keyval != '\0'))   {
 424  426                          return (keyval);
 425  427                  }
 426  428          }
 427  429          return (NULL);
 428  430  }
 429  431  
 430  432  static const char *
 431  433  check_label(const char *labelstr)
 432  434  {
 433  435          int     err;
 434  436          m_label_t *lbl = NULL;
 435  437  
 436  438          if (!is_system_labeled())
 437  439                  return (NULL);
 438  440  
 439  441          err = str_to_label(labelstr, &lbl, MAC_LABEL, L_NO_CORRECTION, NULL);
 440  442          m_label_free(lbl);
 441  443  
 442  444          if (err == -1)
 443  445                  return (labelstr);
 444  446  
 445  447          return (NULL);
 446  448  }
 447  449  
 448  450  static const char *
 449  451  check_idlecmd(const char *cmd)
 450  452  {
 451  453          if ((strcmp(cmd, USERATTR_IDLECMD_LOCK_KW) != 0) &&
 452  454              (strcmp(cmd, USERATTR_IDLECMD_LOGOUT_KW) != 0)) {
 453  455                  return (cmd);
 454  456          }
 455  457  
 456  458          return (NULL);
 457  459  }
 458  460  
 459  461  static const char *
 460  462  check_idletime(const char *time)
 461  463  {
 462  464          int             c;
 463  465          unsigned char   *up = (unsigned char *)time;
 464  466  
 465  467          c = *up;
 466  468          while (c != '\0') {
 467  469                  if (!isdigit(c))
 468  470                          return (time);
 469  471                  c = *++up;
 470  472          }
 471  473  
 472  474          return (NULL);
 473  475  }
 474  476  
 475  477  static const char *
 476  478  check_auditflags(const char *auditflags)
 477  479  {
 478  480          au_mask_t mask;
 479  481          char    *flags;
 480  482          char    *last = NULL;
 481  483          char    *err = "NULL";
 482  484  
 483  485          /* if deleting audit_flags */
 484  486          if (*auditflags == '\0') {
 485  487                  return (NULL);
 486  488          }
 487  489  
 488  490          if ((flags = _strdup_null((char *)auditflags)) == NULL) {
 489  491                  errmsg(M_NOSPACE);
 490  492                  exit(EX_FAILURE);
 491  493          }
 492  494  
 493  495          if (!__chkflags(_strtok_escape(flags, KV_AUDIT_DELIMIT, &last), &mask,
 494  496              B_FALSE, &err)) {
 495  497                  (void) snprintf(auditerr, sizeof (auditerr),
 496  498                      "always mask \"%s\"", err);
 497  499                  free(flags);
 498  500                  return (auditerr);
 499  501          }
 500  502          if (!__chkflags(_strtok_escape(NULL, KV_AUDIT_DELIMIT, &last), &mask,
 501  503              B_FALSE, &err)) {
 502  504                  (void) snprintf(auditerr, sizeof (auditerr),
 503  505                      "never mask \"%s\"", err);
 504  506                  free(flags);
 505  507                  return (auditerr);
 506  508          }
 507  509          if (last != NULL) {
 508  510                  (void) snprintf(auditerr, sizeof (auditerr), "\"%s\"",
 509  511                      auditflags);
 510  512                  free(flags);
 511  513                  return (auditerr);
 512  514          }
 513  515          free(flags);
 514  516  
 515  517          return (NULL);
 516  518  }
  
    | 
      ↓ open down ↓ | 
    309 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX