Print this page
onc plus-be-gone

Split Close
Expand all
Collapse all
          --- old/usr/src/cmd/login/login.c
          +++ new/usr/src/cmd/login/login.c
↓ open down ↓ 16 lines elided ↑ open up ↑
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  
  22   22  /*
  23   23   * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  24   24   * Use is subject to license terms.
  25   25   */
  26   26  
  27      -/* ONC_PLUS EXTRACT START */
  28   27  /*      Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
  29   28  /*        All Rights Reserved   */
  30   29  
  31   30  /*
  32   31   * University Copyright- Copyright (c) 1982, 1986, 1988
  33   32   * The Regents of the University of California
  34   33   * All Rights Reserved
  35   34   *
  36   35   * University Acknowledgment- Portions of this document are derived from
  37   36   * software developed by the University of California, Berkeley, and its
  38   37   * contributors.
  39   38   */
  40   39  
  41   40  /*      Copyright (c) 1987, 1988 Microsoft Corporation  */
  42   41  /*        All Rights Reserved   */
  43   42  
  44      -/* ONC_PLUS EXTRACT END */
  45      -
  46   43  /*
  47   44   * For a complete reference to login(1), see the manual page.  However,
  48   45   * login has accreted some intentionally undocumented options, which are
  49   46   * explained here:
  50   47   *
  51   48   * -a: This legacy flag appears to be unused.
  52   49   *
  53   50   * -f <username>: This flag was introduced by PSARC 1995/039 in support
  54   51   *    of Kerberos.  But it's not used by Sun's Kerberos implementation.
  55   52   *    It is however employed by zlogin(1), since it allows one to tell
↓ open down ↓ 103 lines elided ↑ open up ↑
 159  156  /*
 160  157   * Various useful files and string constants
 161  158   */
 162  159  #define SHELL           "/usr/bin/sh"
 163  160  #define SHELL2          "/sbin/sh"
 164  161  #define SUBLOGIN        "<!sublogin>"
 165  162  #define LASTLOG         "/var/adm/lastlog"
 166  163  #define PROG_NAME       "login"
 167  164  #define HUSHLOGIN       ".hushlogin"
 168  165  
 169      -/* ONC_PLUS EXTRACT START */
 170  166  /*
 171  167   * Array and Buffer sizes
 172  168   */
 173  169  #define PBUFSIZE 8      /* max significant characters in a password */
 174      -/* ONC_PLUS EXTRACT END */
 175  170  #define MAXARGS 63      /* change value below if changing this */
 176  171  #define MAXARGSWIDTH 2  /* log10(MAXARGS) */
 177  172  #define MAXENV 1024
 178  173  #define MAXLINE 2048
 179  174  
 180  175  /*
 181  176   * Miscellaneous constants
 182  177   */
 183  178  #define ROOTUID         0
 184  179  #define ERROR           1
↓ open down ↓ 10 lines elided ↑ open up ↑
 195  190  static int count = 1;
 196  191  
 197  192  /*
 198  193   * error value for login_exit() audit output (0 == no audit record)
 199  194   */
 200  195  static int      audit_error = 0;
 201  196  
 202  197  /*
 203  198   * Externs a plenty
 204  199   */
 205      -/* ONC_PLUS EXTRACT START */
 206  200  extern  int     getsecretkey();
 207      -/* ONC_PLUS EXTRACT START */
 208  201  
 209  202  /*
 210  203   * The current user name
 211  204   */
 212  205  static  char    user_name[NMAX];
 213  206  static  char    minusnam[16] = "-";
 214  207  
 215  208  /*
 216  209   * login_pid, used to find utmpx entry to update.
 217  210   */
↓ open down ↓ 39 lines elided ↑ open up ↑
 257  250  static char progname[MAX_PAMSERVICE_LEN];
 258  251  
 259  252  
 260  253  /*
 261  254   * Strings used to prompt the user.
 262  255   */
 263  256  static  char    loginmsg[] = "login: ";
 264  257  static  char    passwdmsg[] = "Password:";
 265  258  static  char    incorrectmsg[] = "Login incorrect\n";
 266  259  
 267      -/* ONC_PLUS EXTRACT START */
 268  260  /*
 269  261   * Password file support
 270  262   */
 271  263  static  struct  passwd *pwd = NULL;
 272  264  static  char    remote_host[HMAX];
 273  265  static  char    zone_name[ZONENAME_MAX];
 274  266  
 275  267  /*
 276  268   * Illegal passwd entries.
 277  269   */
 278  270  static  struct  passwd nouser = { "", "no:password", (uid_t)-1 };
 279      -/* ONC_PLUS EXTRACT END */
 280  271  
 281  272  /*
 282  273   * Log file support
 283  274   */
 284  275  static  char    *log_entry[LOGTRYS];
 285  276  static  int     writelog = 0;
 286  277  static  int     lastlogok = 0;
 287  278  static  struct lastlog ll;
 288  279  static  int     dosyslog = 0;
 289  280  static  int     flogin = MAXTRYS;       /* flag for SYSLOG_FAILED_LOGINS */
↓ open down ↓ 46 lines elided ↑ open up ↑
 336  327  static  boolean_t hflag = B_FALSE;
 337  328  static  boolean_t rflag = B_FALSE;
 338  329  static  boolean_t zflag = B_FALSE;
 339  330  
 340  331  /*
 341  332   * Remote login support
 342  333   */
 343  334  static  char    rusername[NMAX+1], lusername[NMAX+1];
 344  335  static  char    terminal[MAXPATHLEN];
 345  336  
 346      -/* ONC_PLUS EXTRACT START */
 347  337  /*
 348  338   * Pre-authentication flag support
 349  339   */
 350  340  static  int     fflag;
 351  341  
 352  342  static char ** getargs(char *);
 353  343  
 354  344  static int login_conv(int, struct pam_message **,
 355  345      struct pam_response **, void *);
 356  346  
 357  347  static struct pam_conv pam_conv = {login_conv, NULL};
 358  348  static pam_handle_t *pamh;      /* Authentication handle */
 359      -/* ONC_PLUS EXTRACT END */
 360  349  
 361  350  /*
 362  351   * Function declarations
 363  352   */
 364  353  static  void    turn_on_logging(void);
 365  354  static  void    defaults(void);
 366  355  static  void    usage(void);
 367  356  static  void    process_rlogin(void);
 368      -/* ONC_PLUS EXTRACT START */
 369  357  static  void    login_authenticate();
 370  358  static  void    setup_credentials(void);
 371      -/* ONC_PLUS EXTRACT END */
 372  359  static  void    adjust_nice(void);
 373  360  static  void    update_utmpx_entry(int);
 374  361  static  void    establish_user_environment(char **);
 375  362  static  void    print_banner(void);
 376  363  static  void    display_last_login_time(void);
 377  364  static  void    exec_the_shell(void);
 378  365  static  int     process_chroot_logins(void);
 379  366  static  void    chdir_to_dir_user(void);
 380  367  static  void    check_log(void);
 381  368  static  void    validate_account(void);
↓ open down ↓ 3 lines elided ↑ open up ↑
 385  372  static  int     legalenvvar(char *);
 386  373  static  void    check_for_console(void);
 387  374  static  void    check_for_dueling_unix(char *);
 388  375  static  void    get_user_name(void);
 389  376  static  uint_t  get_audit_id(void);
 390  377  static  void    login_exit(int)__NORETURN;
 391  378  static  int     logins_disabled(char *);
 392  379  static  void    log_bad_attempts(void);
 393  380  static  int     is_number(char *);
 394  381  
 395      -/* ONC_PLUS EXTRACT START */
 396  382  /*
 397  383   *                      *** main ***
 398  384   *
 399  385   *      The primary flow of control is directed in this routine.
 400  386   *      Control moves in line from top to bottom calling subfunctions
 401  387   *      which perform the bulk of the work.  Many of these calls exit
 402  388   *      when a fatal error is encountered and do not return to main.
 403  389   *
 404  390   *
 405  391   */
 406  392  
 407  393  int
 408  394  main(int argc, char *argv[], char **renvp)
 409  395  {
 410      -/* ONC_PLUS EXTRACT END */
 411  396          int sublogin;
 412  397          int pam_rc;
 413  398  
 414  399          login_pid = getpid();
 415  400  
 416  401          /*
 417  402           * Set up Defaults and flags
 418  403           */
 419  404          defaults();
 420  405          SCPYL(progname, PROG_NAME);
↓ open down ↓ 41 lines elided ↑ open up ↑
 462  447  
 463  448          /*
 464  449           * if devicename is not passed as argument, call ttyname(0)
 465  450           */
 466  451          if (ttyn == NULL) {
 467  452                  ttyn = ttyname(0);
 468  453                  if (ttyn == NULL)
 469  454                          ttyn = "/dev/???";
 470  455          }
 471  456  
 472      -/* ONC_PLUS EXTRACT START */
 473  457          /*
 474  458           * Call pam_start to initiate a PAM authentication operation
 475  459           */
 476  460  
 477  461          if ((pam_rc = pam_start(progname, user_name, &pam_conv, &pamh))
 478  462              != PAM_SUCCESS) {
 479  463                  audit_error = ADT_FAIL_PAM + pam_rc;
 480  464                  login_exit(1);
 481  465          }
 482  466          if ((pam_rc = pam_set_item(pamh, PAM_TTY, ttyn)) != PAM_SUCCESS) {
↓ open down ↓ 18 lines elided ↑ open up ↑
 501  485                  krb5_data.principal = identity;
 502  486                  krb5_data.flags = SUNW_PAM_KRB5_ALREADY_AUTHENTICATED;
 503  487  
 504  488                  pam_rep_data.type = repository;
 505  489                  pam_rep_data.scope = (void *)&krb5_data;
 506  490                  pam_rep_data.scope_len = sizeof (krb5_data);
 507  491  
 508  492                  (void) pam_set_item(pamh, PAM_REPOSITORY,
 509  493                      (void *)&pam_rep_data);
 510  494          }
 511      -/* ONC_PLUS EXTRACT END */
 512  495  
 513  496          /*
 514  497           * Open the log file which contains a record of successful and failed
 515  498           * login attempts
 516  499           */
 517  500          turn_on_logging();
 518  501  
 519  502          /*
 520  503           * say "hi" to syslogd ..
 521  504           */
 522  505          openlog("login", 0, LOG_AUTH);
 523  506  
 524  507          /*
 525  508           * Do special processing for -r (rlogin) flag
 526  509           */
 527  510          if (rflag)
 528  511                  process_rlogin();
 529  512  
 530      -/* ONC_PLUS EXTRACT START */
 531  513          /*
 532  514           * validate user
 533  515           */
 534  516          /* we are already authenticated. fill in what we must, then continue */
 535  517          if (fflag) {
 536      -/* ONC_PLUS EXTRACT END */
 537  518                  if ((pwd = getpwnam(user_name)) == NULL) {
 538  519                          audit_error = ADT_FAIL_VALUE_USERNAME;
 539  520  
 540  521                          log_bad_attempts();
 541  522                          (void) printf("Login failed: unknown user '%s'.\n",
 542  523                              user_name);
 543  524                          login_exit(1);
 544  525                  }
 545      -/* ONC_PLUS EXTRACT START */
 546  526          } else {
 547  527                  /*
 548  528                   * Perform the primary login authentication activity.
 549  529                   */
 550  530                  login_authenticate();
 551  531          }
 552      -/* ONC_PLUS EXTRACT END */
 553  532  
 554  533          /* change root login, then we exec another login and try again */
 555  534          if (process_chroot_logins() != OK)
 556  535                  login_exit(1);
 557  536  
 558  537          /*
 559  538           * If root login and not on system console then call exit(2)
 560  539           */
 561  540          check_for_console();
 562  541  
↓ open down ↓ 32 lines elided ↑ open up ↑
 595  574  
 596  575          /* di_devperm_login() sends detailed errors to syslog */
 597  576          if (di_devperm_login((const char *)ttyn, pwd->pw_uid, pwd->pw_gid,
 598  577              NULL) == -1) {
 599  578                  (void) fprintf(stderr, "error processing /etc/logindevperm,"
 600  579                      " see syslog for more details\n");
 601  580          }
 602  581  
 603  582          adjust_nice();          /* passwd file can specify nice value */
 604  583  
 605      -/* ONC_PLUS EXTRACT START */
 606  584          setup_credentials();    /* Set user credentials  - exits on failure */
 607  585  
 608  586          /*
 609  587           * NOTE: telnetd and rlogind rely upon this updating of utmpx
 610  588           * to indicate that the authentication completed  successfully,
 611  589           * pam_open_session was called and therefore they are required to
 612  590           * call pam_close_session.
 613  591           */
 614  592          update_utmpx_entry(sublogin);
 615  593  
↓ open down ↓ 5 lines elided ↑ open up ↑
 621  599          /*
 622  600           * Set up the basic environment for the exec.  This includes
 623  601           * HOME, PATH, LOGNAME, SHELL, TERM, TZ, HZ, and MAIL.
 624  602           */
 625  603          chdir_to_dir_user();
 626  604  
 627  605          establish_user_environment(renvp);
 628  606  
 629  607          (void) pam_end(pamh, PAM_SUCCESS);      /* Done using PAM */
 630  608          pamh = NULL;
 631      -/* ONC_PLUS EXTRACT END */
 632  609  
 633  610          if (pwd->pw_uid == 0) {
 634  611                  if (dosyslog) {
 635  612                          if (remote_host[0]) {
 636  613                                  syslog(LOG_NOTICE, "ROOT LOGIN %s FROM %.*s",
 637  614                                      ttyn, HMAX, remote_host);
 638  615                          } else
 639  616                                  syslog(LOG_NOTICE, "ROOT LOGIN %s", ttyn);
 640  617                  }
 641  618          }
↓ open down ↓ 33 lines elided ↑ open up ↑
 675  652          return (0);
 676  653  }
 677  654  
 678  655  
 679  656  /*
 680  657   *                      *** Utility functions ***
 681  658   */
 682  659  
 683  660  
 684  661  
 685      -/* ONC_PLUS EXTRACT START */
 686  662  /*
 687  663   * donothing & catch    - Signal catching functions
 688  664   */
 689  665  
 690  666  /*ARGSUSED*/
 691  667  static void
 692  668  donothing(int sig)
 693  669  {
 694  670          if (pamh)
 695  671                  (void) pam_end(pamh, PAM_ABORT);
 696  672  }
 697      -/* ONC_PLUS EXTRACT END */
 698  673  
 699  674  #ifdef notdef
 700  675  static  int     intrupt;
 701  676  
 702  677  /*ARGSUSED*/
 703  678  static void
 704  679  catch(int sig)
 705  680  {
 706  681          ++intrupt;
 707  682  }
↓ open down ↓ 100 lines elided ↑ open up ↑
 808  783                          if (!(log_entry[i] = malloc((size_t)ENT_SIZE))) {
 809  784                                  writelog = 0;
 810  785                                  break;
 811  786                          }
 812  787                          *log_entry[i] = '\0';
 813  788                  }
 814  789          }
 815  790  }
 816  791  
 817  792  
 818      -/* ONC_PLUS EXTRACT START */
 819  793  /*
 820  794   * login_conv():
 821  795   *      This is the conv (conversation) function called from
 822  796   *      a PAM authentication module to print error messages
 823  797   *      or garner information from the user.
 824  798   */
 825  799  /*ARGSUSED*/
 826  800  static int
 827  801  login_conv(int num_msg, struct pam_message **msg,
 828  802      struct pam_response **response, void *appdata_ptr)
↓ open down ↓ 145 lines elided ↑ open up ↑
 974  948          SCPYL(user_name, user);
 975  949          check_for_dueling_unix(user_name);
 976  950  
 977  951          if (((pwd = getpwnam(user_name)) == NULL) &&
 978  952              (error != PAM_USER_UNKNOWN)) {
 979  953                  return (PAM_SYSTEM_ERR);
 980  954          }
 981  955  
 982  956          return (error);
 983  957  }
 984      -/* ONC_PLUS EXTRACT END */
 985  958  
 986  959  /*
 987  960   * quotec               - Called by getargs
 988  961   */
 989  962  
 990  963  static int
 991  964  quotec(void)
 992  965  {
 993  966          int c, i, num;
 994  967  
↓ open down ↓ 786 lines elided ↑ open up ↑
1781 1754                          (void) sleep(Disabletime);
1782 1755                          exit(1);
1783 1756                  } else {
1784 1757                          (void) printf("No directory! Logging in with home=/\n");
1785 1758                          pwd->pw_dir = "/";
1786 1759                  }
1787 1760          }
1788 1761  }
1789 1762  
1790 1763  
1791      -/* ONC_PLUS EXTRACT START */
1792 1764  /*
1793 1765   * login_authenticate   - Performs the main authentication work
1794 1766   *                        1. Prints the login prompt
1795 1767   *                        2. Requests and verifys the password
1796 1768   *                        3. Checks the port password
1797 1769   */
1798 1770  
1799 1771  static void
1800 1772  login_authenticate(void)
1801 1773  {
↓ open down ↓ 158 lines elided ↑ open up ↑
1960 1932          }
1961 1933  
1962 1934          /*
1963 1935           * Record successful login and fork process that records logout.
1964 1936           * We have to do this after setting credentials because pam_setcred()
1965 1937           * loads key audit info into the cred, but before setuid() so audit
1966 1938           * system calls will work.
1967 1939           */
1968 1940          audit_success(get_audit_id(), pwd, zone_name);
1969 1941  }
1970      -/* ONC_PLUS EXTRACT END */
1971 1942  
1972 1943  static uint_t
1973 1944  get_audit_id(void)
1974 1945  {
1975 1946          if (rflag)
1976 1947                  return (ADT_rlogin);
1977 1948          else if (hflag)
1978 1949                  return (ADT_telnet);
1979 1950          else if (zflag)
1980 1951                  return (ADT_zlogin);
↓ open down ↓ 39 lines elided ↑ open up ↑
2020 1991                  while (pwd->pw_gecos[i] >= '0' && pwd->pw_gecos[i] <= '9')
2021 1992                          pri = (pri * 10) + pwd->pw_gecos[i++] - '0';
2022 1993  
2023 1994                  if (mflg)
2024 1995                          pri = -pri;
2025 1996  
2026 1997                  (void) nice(pri);
2027 1998          }
2028 1999  }
2029 2000  
2030      -/* ONC_PLUS EXTRACT START */
2031 2001  /*
2032 2002   * update_utmpx_entry   - Searchs for the correct utmpx entry, making an
2033 2003   *                        entry there if it finds one, otherwise exits.
2034 2004   */
2035 2005  
2036 2006  static void
2037 2007  update_utmpx_entry(int sublogin)
2038 2008  {
2039 2009          int     err;
2040 2010          char    *user;
↓ open down ↓ 16 lines elided ↑ open up ↑
2057 2027          if ((err = pam_open_session(pamh, 0)) != PAM_SUCCESS) {
2058 2028                  audit_error = ADT_FAIL_PAM + err;
2059 2029                  login_exit(1);
2060 2030          }
2061 2031  
2062 2032          if ((err = pam_get_item(pamh, PAM_USER, (void **) &user)) !=
2063 2033              PAM_SUCCESS) {
2064 2034                  audit_error = ADT_FAIL_PAM + err;
2065 2035                  login_exit(1);
2066 2036          }
2067      -/* ONC_PLUS EXTRACT END */
2068 2037  
2069 2038          (void) memset((void *)&utmpx, 0, sizeof (utmpx));
2070 2039          (void) time(&utmpx.ut_tv.tv_sec);
2071 2040          utmpx.ut_pid = getpid();
2072 2041  
2073 2042          if (rflag || hflag) {
2074 2043                  SCPYN(utmpx.ut_host, remote_host);
2075 2044                  tmplen = strlen(remote_host) + 1;
2076 2045                  if (tmplen < sizeof (utmpx.ut_host))
2077 2046                          utmpx.ut_syslen = tmplen;
↓ open down ↓ 47 lines elided ↑ open up ↑
2125 2094  
2126 2095                          audit_error = ADT_FAIL_VALUE_PROGRAM;
2127 2096                          login_exit(1);
2128 2097                  }
2129 2098          } else {
2130 2099                  /* Now attempt to write out this entry to the wtmp file if */
2131 2100                  /* we were successful in getting it from the utmpx file and */
2132 2101                  /* the wtmp file exists.                                   */
2133 2102                  updwtmpx(WTMPX_FILE, &utmpx);
2134 2103          }
2135      -/* ONC_PLUS EXTRACT START */
2136 2104  }
2137 2105  
2138 2106  
2139 2107  
2140 2108  /*
2141 2109   * process_chroot_logins        - Chroots to the specified subdirectory and
2142 2110   *                                re executes login.
2143 2111   */
2144 2112  
2145 2113  static int
↓ open down ↓ 13 lines elided ↑ open up ↑
2159 2127                          audit_failure(get_audit_id(),
2160 2128                              ADT_FAIL_VALUE_CHDIR_FAILED,
2161 2129                              pwd, remote_host, ttyn, zone_name);
2162 2130  
2163 2131                          return (ERROR);
2164 2132                  }
2165 2133                  /*
2166 2134                   * Set the environment flag <!sublogin> so that the next login
2167 2135                   * knows that it is a sublogin.
2168 2136                   */
2169      -/* ONC_PLUS EXTRACT END */
2170 2137                  envinit[0] = SUBLOGIN;
2171 2138                  envinit[1] = (char *)NULL;
2172 2139                  (void) printf("Subsystem root: %s\n", pwd->pw_dir);
2173 2140                  (void) execle("/usr/bin/login", "login", (char *)0,
2174 2141                      &envinit[0]);
2175 2142                  (void) execle("/etc/login", "login", (char *)0, &envinit[0]);
2176 2143                  (void) printf("No /usr/bin/login or /etc/login on root\n");
2177 2144  
2178 2145                  audit_error = ADT_FAIL_VALUE_PROGRAM;
2179 2146  
2180 2147                  login_exit(1);
2181 2148          }
2182 2149          return (OK);
2183      -/* ONC_PLUS EXTRACT START */
2184 2150  }
2185 2151  
2186 2152  /*
2187 2153   * establish_user_environment   - Set up the new users enviornment
2188 2154   */
2189 2155  
2190 2156  static void
2191 2157  establish_user_environment(char **renvp)
2192 2158  {
2193 2159          int i, j, k, l_index, length, idx = 0;
↓ open down ↓ 27 lines elided ↑ open up ↑
2221 2187          if (pam_env != 0) {
2222 2188                  while (pam_env[idx] != 0) {
2223 2189                          if (legalenvvar(pam_env[idx])) {
2224 2190                                  envinit[basicenv] = pam_env[idx];
2225 2191                                  basicenv++;
2226 2192                          }
2227 2193                          idx++;
2228 2194                  }
2229 2195          }
2230 2196          (void) memcpy(&envinit[basicenv], newenv, sizeof (newenv));
2231      -/* ONC_PLUS EXTRACT END */
2232 2197  
2233 2198          /* Set up environment */
2234 2199          if (rflag) {
2235 2200                  ENVSTRNCAT(term, terminal);
2236 2201          } else if (hflag) {
2237 2202                  if (strlen(terminal)) {
2238 2203                          ENVSTRNCAT(term, terminal);
2239 2204                  }
2240 2205          } else {
2241 2206                  char *tp = getenv("TERM");
↓ open down ↓ 345 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX