Diff for /embedaddon/sudo/plugins/sudoers/auth/pam.c between versions 1.1.1.3 and 1.1.1.4

version 1.1.1.3, 2013/07/22 10:46:12 version 1.1.1.4, 2013/10/14 07:56:35
Line 79 Line 79
 static int converse(int, PAM_CONST struct pam_message **,  static int converse(int, PAM_CONST struct pam_message **,
                     struct pam_response **, void *);                      struct pam_response **, void *);
 static char *def_prompt = "Password:";  static char *def_prompt = "Password:";
 static bool sudo_pam_cred_established;  
 static bool sudo_pam_authenticated;  
 static int getpass_error;  static int getpass_error;
 static pam_handle_t *pamh;  static pam_handle_t *pamh;
   
Line 92  sudo_pam_init(struct passwd *pw, sudo_auth *auth) Line 90  sudo_pam_init(struct passwd *pw, sudo_auth *auth)
     debug_decl(sudo_pam_init, SUDO_DEBUG_AUTH)      debug_decl(sudo_pam_init, SUDO_DEBUG_AUTH)
   
     /* Initial PAM setup */      /* Initial PAM setup */
    if (auth != NULL)    auth->data = (void *) &pam_status;
        auth->data = (void *) &pam_status; 
     pam_conv.conv = converse;      pam_conv.conv = converse;
#ifdef HAVE_PAM_LOGIN    pam_status = pam_start(ISSET(sudo_mode, MODE_LOGIN_SHELL) ?
    if (ISSET(sudo_mode, MODE_LOGIN_SHELL))        def_pam_login_service : def_pam_service, pw->pw_name, &pam_conv, &pamh);
        pam_status = pam_start("sudo-i", pw->pw_name, &pam_conv, &pamh); 
    else 
#endif 
        pam_status = pam_start("sudo", pw->pw_name, &pam_conv, &pamh); 
     if (pam_status != PAM_SUCCESS) {      if (pam_status != PAM_SUCCESS) {
         log_warning(USE_ERRNO|NO_MAIL, N_("unable to initialize PAM"));          log_warning(USE_ERRNO|NO_MAIL, N_("unable to initialize PAM"));
         debug_return_int(AUTH_FATAL);          debug_return_int(AUTH_FATAL);
Line 125  sudo_pam_init(struct passwd *pw, sudo_auth *auth) Line 118  sudo_pam_init(struct passwd *pw, sudo_auth *auth)
     else      else
         (void) pam_set_item(pamh, PAM_TTY, user_ttypath);          (void) pam_set_item(pamh, PAM_TTY, user_ttypath);
   
       /*
        * If PAM session and setcred support is disabled we don't
        * need to keep a sudo process around to close the session.
        */
       if (!def_pam_session && !def_pam_setcred)
           auth->end_session = NULL;
   
     debug_return_int(AUTH_SUCCESS);      debug_return_int(AUTH_SUCCESS);
 }  }
   
Line 144  sudo_pam_verify(struct passwd *pw, char *prompt, sudo_ Line 144  sudo_pam_verify(struct passwd *pw, char *prompt, sudo_
             *pam_status = pam_acct_mgmt(pamh, PAM_SILENT);              *pam_status = pam_acct_mgmt(pamh, PAM_SILENT);
             switch (*pam_status) {              switch (*pam_status) {
                 case PAM_SUCCESS:                  case PAM_SUCCESS:
                     sudo_pam_authenticated = true;  
                     debug_return_int(AUTH_SUCCESS);                      debug_return_int(AUTH_SUCCESS);
                 case PAM_AUTH_ERR:                  case PAM_AUTH_ERR:
                     log_warning(NO_MAIL, N_("account validation failure, "                      log_warning(NO_MAIL, N_("account validation failure, "
Line 196  sudo_pam_cleanup(struct passwd *pw, sudo_auth *auth) Line 195  sudo_pam_cleanup(struct passwd *pw, sudo_auth *auth)
     int *pam_status = (int *) auth->data;      int *pam_status = (int *) auth->data;
     debug_decl(sudo_pam_cleanup, SUDO_DEBUG_AUTH)      debug_decl(sudo_pam_cleanup, SUDO_DEBUG_AUTH)
   
    /* If successful, we can't close the session until pam_end_session() */    /* If successful, we can't close the session until sudo_pam_end_session() */
    if (*pam_status == AUTH_SUCCESS)    if (*pam_status != PAM_SUCCESS || auth->end_session == NULL) {
        debug_return_int(AUTH_SUCCESS);        *pam_status = pam_end(pamh, *pam_status | PAM_DATA_SILENT);
        pamh = NULL;
    *pam_status = pam_end(pamh, *pam_status | PAM_DATA_SILENT);    }
    pamh = NULL; 
     debug_return_int(*pam_status == PAM_SUCCESS ? AUTH_SUCCESS : AUTH_FAILURE);      debug_return_int(*pam_status == PAM_SUCCESS ? AUTH_SUCCESS : AUTH_FAILURE);
 }  }
   
 int  int
 sudo_pam_begin_session(struct passwd *pw, char **user_envp[], sudo_auth *auth)  sudo_pam_begin_session(struct passwd *pw, char **user_envp[], sudo_auth *auth)
 {  {
    int status = PAM_SUCCESS;    int status = AUTH_SUCCESS;
     int *pam_status = (int *) auth->data;
     debug_decl(sudo_pam_begin_session, SUDO_DEBUG_AUTH)      debug_decl(sudo_pam_begin_session, SUDO_DEBUG_AUTH)
   
     /*      /*
Line 232  sudo_pam_begin_session(struct passwd *pw, char **user_ Line 231  sudo_pam_begin_session(struct passwd *pw, char **user_
   
     /*      /*
      * Set credentials (may include resource limits, device ownership, etc).       * Set credentials (may include resource limits, device ownership, etc).
     * We don't check the return value here because in Linux-PAM 0.75     * We don't worry about a failure from pam_setcred() since with
     * it returns the last saved return code, not the return code     * stacked PAM auth modules a failure from one module may override
     * for the setcred module.  Because we haven't called pam_authenticate(),     * PAM_SUCCESS from another.  For example, given a non-local user,
     * this is not set and so pam_setcred() returns PAM_PERM_DENIED.     * pam_unix will fail but pam_ldap or pam_sss may succeed, but if
     * We can't call pam_acct_mgmt() with Linux-PAM for a similar reason.     * pam_unix is first in the stack, pam_setcred() will fail.
      */       */
    status = pam_setcred(pamh, PAM_ESTABLISH_CRED);    if (def_pam_setcred)
    if (status == PAM_SUCCESS) {        (void) pam_setcred(pamh, PAM_ESTABLISH_CRED);
        sudo_pam_cred_established = true;
    } else if (sudo_pam_authenticated) {    if (def_pam_session) {
        const char *s = pam_strerror(pamh, status);        *pam_status = pam_open_session(pamh, 0);
        if (s != NULL)        if (*pam_status != PAM_SUCCESS) {
            log_warning(NO_MAIL, N_("unable to establish credentials: %s"), s);            (void) pam_end(pamh, *pam_status | PAM_DATA_SILENT);
        goto done;            pamh = NULL;
             status = AUTH_FAILURE;
         }
     }      }
   
 #ifdef HAVE_PAM_GETENVLIST  #ifdef HAVE_PAM_GETENVLIST
Line 257  sudo_pam_begin_session(struct passwd *pw, char **user_ Line 258  sudo_pam_begin_session(struct passwd *pw, char **user_
     if (user_envp != NULL) {      if (user_envp != NULL) {
         char **pam_envp = pam_getenvlist(pamh);          char **pam_envp = pam_getenvlist(pamh);
         if (pam_envp != NULL) {          if (pam_envp != NULL) {
            /* Merge pam env with user env but do not overwrite. */            /* Merge pam env with user env. */
             env_init(*user_envp);              env_init(*user_envp);
            env_merge(pam_envp, false);            env_merge(pam_envp);
             *user_envp = env_get();              *user_envp = env_get();
             env_init(NULL);              env_init(NULL);
             efree(pam_envp);              efree(pam_envp);
Line 268  sudo_pam_begin_session(struct passwd *pw, char **user_ Line 269  sudo_pam_begin_session(struct passwd *pw, char **user_
     }      }
 #endif /* HAVE_PAM_GETENVLIST */  #endif /* HAVE_PAM_GETENVLIST */
   
     if (def_pam_session) {  
         status = pam_open_session(pamh, 0);  
         if (status != PAM_SUCCESS) {  
             (void) pam_end(pamh, status | PAM_DATA_SILENT);  
             pamh = NULL;  
         }  
     }  
   
 done:  done:
    debug_return_int(status == PAM_SUCCESS ? AUTH_SUCCESS : AUTH_FAILURE);    debug_return_int(status);
 }  }
   
 int  int
 sudo_pam_end_session(struct passwd *pw, sudo_auth *auth)  sudo_pam_end_session(struct passwd *pw, sudo_auth *auth)
 {  {
    int status = PAM_SUCCESS;    int status = AUTH_SUCCESS;
     debug_decl(sudo_pam_end_session, SUDO_DEBUG_AUTH)      debug_decl(sudo_pam_end_session, SUDO_DEBUG_AUTH)
   
     if (pamh != NULL) {      if (pamh != NULL) {
Line 295  sudo_pam_end_session(struct passwd *pw, sudo_auth *aut Line 288  sudo_pam_end_session(struct passwd *pw, sudo_auth *aut
         (void) pam_set_item(pamh, PAM_USER, pw->pw_name);          (void) pam_set_item(pamh, PAM_USER, pw->pw_name);
         if (def_pam_session)          if (def_pam_session)
             (void) pam_close_session(pamh, PAM_SILENT);              (void) pam_close_session(pamh, PAM_SILENT);
        if (sudo_pam_cred_established)        if (def_pam_setcred)
             (void) pam_setcred(pamh, PAM_DELETE_CRED | PAM_SILENT);              (void) pam_setcred(pamh, PAM_DELETE_CRED | PAM_SILENT);
        status = pam_end(pamh, PAM_SUCCESS | PAM_DATA_SILENT);        if (pam_end(pamh, PAM_SUCCESS | PAM_DATA_SILENT) != PAM_SUCCESS)
             status = AUTH_FAILURE;
         pamh = NULL;          pamh = NULL;
     }      }
   
    debug_return_int(status == PAM_SUCCESS ? AUTH_SUCCESS : AUTH_FAILURE);    debug_return_int(status);
 }  }
   
 /*  /*
Line 322  converse(int num_msg, PAM_CONST struct pam_message **m Line 316  converse(int num_msg, PAM_CONST struct pam_message **m
   
     if ((*response = malloc(num_msg * sizeof(struct pam_response))) == NULL)      if ((*response = malloc(num_msg * sizeof(struct pam_response))) == NULL)
         debug_return_int(PAM_SYSTEM_ERR);          debug_return_int(PAM_SYSTEM_ERR);
    zero_bytes(*response, num_msg * sizeof(struct pam_response));    memset(*response, 0, num_msg * sizeof(struct pam_response));
   
     for (pr = *response, pm = *msg, n = num_msg; n--; pr++, pm++) {      for (pr = *response, pm = *msg, n = num_msg; n--; pr++, pm++) {
         type = SUDO_CONV_PROMPT_ECHO_OFF;          type = SUDO_CONV_PROMPT_ECHO_OFF;
Line 366  converse(int num_msg, PAM_CONST struct pam_message **m Line 360  converse(int num_msg, PAM_CONST struct pam_message **m
 #endif  #endif
                 }                  }
                 pr->resp = estrdup(pass);                  pr->resp = estrdup(pass);
                zero_bytes(pass, strlen(pass));                memset_s(pass, SUDO_CONV_REPL_MAX, 0, strlen(pass));
                 break;                  break;
             case PAM_TEXT_INFO:              case PAM_TEXT_INFO:
                 if (pm->msg)                  if (pm->msg)
Line 390  done: Line 384  done:
         /* Zero and free allocated memory and return an error. */          /* Zero and free allocated memory and return an error. */
         for (pr = *response, n = num_msg; n--; pr++) {          for (pr = *response, n = num_msg; n--; pr++) {
             if (pr->resp != NULL) {              if (pr->resp != NULL) {
                zero_bytes(pr->resp, strlen(pr->resp));                memset_s(pr->resp, SUDO_CONV_REPL_MAX, 0, strlen(pr->resp));
                 free(pr->resp);                  free(pr->resp);
                 pr->resp = NULL;                  pr->resp = NULL;
             }              }
         }          }
         zero_bytes(*response, num_msg * sizeof(struct pam_response));  
         free(*response);          free(*response);
         *response = NULL;          *response = NULL;
     }      }

Removed from v.1.1.1.3  
changed lines
  Added in v.1.1.1.4


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>