s3-pam_winbind: Fix the build.
[samba.git] / nsswitch / pam_winbind.c
index 0eb24a26934db0226cc6e0db83b07d332bc2ceeb..caae5896c45ca3f69d113940bf2ee4bef1ff0de9 100644 (file)
@@ -437,13 +437,13 @@ static int _pam_parse(const pam_handle_t *pamh,
                ctrl |= WINBIND_SILENT;
        }
 
-       if (iniparser_getstr(d, CONST_DISCARD(char *, "global:krb5_ccache_type")) != NULL) {
+       if (iniparser_getstring(d, CONST_DISCARD(char *, "global:krb5_ccache_type"), NULL) != NULL) {
                ctrl |= WINBIND_KRB5_CCACHE_TYPE;
        }
 
-       if ((iniparser_getstr(d, CONST_DISCARD(char *, "global:require-membership-of"))
+       if ((iniparser_getstring(d, CONST_DISCARD(char *, "global:require-membership-of"), NULL)
             != NULL) ||
-           (iniparser_getstr(d, CONST_DISCARD(char *, "global:require_membership_of"))
+           (iniparser_getstring(d, CONST_DISCARD(char *, "global:require_membership_of"), NULL)
             != NULL)) {
                ctrl |= WINBIND_REQUIRED_MEMBERSHIP;
        }
@@ -807,6 +807,43 @@ static int wbc_auth_error_to_pam_error(struct pwb_context *ctx,
        return pam_winbind_request_log(ctx, ret, username, fn);
 }
 
+#if defined(HAVE_PAM_RADIO_TYPE)
+static bool _pam_winbind_change_pwd(struct pwb_context *ctx)
+{
+       struct pam_message msg, *pmsg;
+       struct pam_response *resp = NULL;
+       const char *prompt;
+       int ret;
+       bool retval = false;
+       prompt = _("Do you want to change your password now?");
+       pmsg = &msg;
+       msg.msg_style = PAM_RADIO_TYPE;
+       msg.msg = prompt;
+       ret = converse(ctx->pamh, 1, &pmsg, &resp);
+       if (resp == NULL) {
+               if (ret == PAM_SUCCESS) {
+                       _pam_log(ctx, LOG_CRIT, "pam_winbind: system error!\n");
+                       return false;
+               }
+       }
+       if (ret != PAM_SUCCESS) {
+               return false;
+       }
+       _pam_log(ctx, LOG_CRIT, "Received [%s] reply from application.\n", resp->resp);
+
+       if (strcasecmp(resp->resp, "yes") == 0) {
+               retval = true;
+       }
+
+       _pam_drop_reply(resp, 1);
+       return retval;
+}
+#else
+static bool _pam_winbind_change_pwd(struct pwb_context *ctx)
+{
+       return false;
+}
+#endif
 
 /**
  * send a password expiry message if required
@@ -823,15 +860,22 @@ static bool _pam_send_password_expiry_message(struct pwb_context *ctx,
                                              time_t next_change,
                                              time_t now,
                                              int warn_pwd_expire,
-                                             bool *already_expired)
+                                             bool *already_expired,
+                                             bool *change_pwd)
 {
        int days = 0;
        struct tm tm_now, tm_next_change;
+       bool retval = false;
+       int ret;
 
        if (already_expired) {
                *already_expired = false;
        }
 
+       if (change_pwd) {
+               *change_pwd = false;
+       }
+
        if (next_change <= now) {
                PAM_WB_REMARK_DIRECT(ctx, "NT_STATUS_PASSWORD_EXPIRED");
                if (already_expired) {
@@ -854,15 +898,61 @@ static bool _pam_send_password_expiry_message(struct pwb_context *ctx,
               (tm_now.tm_yday+tm_now.tm_year*365);
 
        if (days == 0) {
-               _make_remark(ctx, PAM_TEXT_INFO,
-                            _("Your password expires today"));
+               ret = _make_remark(ctx, PAM_TEXT_INFO,
+                               _("Your password expires today.\n"));
+
+               /*
+                * If change_pwd and already_expired is null.
+                * We are just sending a notification message.
+                * We don't expect any response in this case.
+                */
+
+               if (!change_pwd && !already_expired) {
+                       return true;
+               }
+
+               /*
+                * successfully sent the warning message.
+                * Give the user a chance to change pwd.
+                */
+               if (ret == PAM_SUCCESS) {
+                       if (change_pwd) {
+                               retval = _pam_winbind_change_pwd(ctx);
+                               if (retval) {
+                                       *change_pwd = true;
+                               }
+                       }
+               }
                return true;
        }
 
        if (days > 0 && days < warn_pwd_expire) {
-               _make_remark_format(ctx, PAM_TEXT_INFO,
-                                   _("Your password will expire in %d %s"),
-                                   days, (days > 1) ? _("days"):_("day"));
+
+               ret = _make_remark_format(ctx, PAM_TEXT_INFO,
+                                       _("Your password will expire in %d %s.\n"),
+                                       days, (days > 1) ? _("days"):_("day"));
+               /*
+                * If change_pwd and already_expired is null.
+                * We are just sending a notification message.
+                * We don't expect any response in this case.
+                */
+
+               if (!change_pwd && !already_expired) {
+                       return true;
+               }
+
+               /*
+                * successfully sent the warning message.
+                * Give the user a chance to change pwd.
+                */
+               if (ret == PAM_SUCCESS) {
+                       if (change_pwd) {
+                               retval = _pam_winbind_change_pwd(ctx);
+                               if (retval) {
+                                       *change_pwd = true;
+                               }
+                       }
+               }
                return true;
        }
 
@@ -883,7 +973,8 @@ static void _pam_warn_password_expiry(struct pwb_context *ctx,
                                      const struct wbcAuthUserInfo *info,
                                      const struct wbcUserPasswordPolicyInfo *policy,
                                      int warn_pwd_expire,
-                                     bool *already_expired)
+                                     bool *already_expired,
+                                     bool *change_pwd)
 {
        time_t now = time(NULL);
        time_t next_change = 0;
@@ -896,6 +987,10 @@ static void _pam_warn_password_expiry(struct pwb_context *ctx,
                *already_expired = false;
        }
 
+       if (change_pwd) {
+               *change_pwd = false;
+       }
+
        /* accounts with WBC_ACB_PWNOEXP set never receive a warning */
        if (info->acct_flags & WBC_ACB_PWNOEXP) {
                return;
@@ -911,7 +1006,8 @@ static void _pam_warn_password_expiry(struct pwb_context *ctx,
 
        if (_pam_send_password_expiry_message(ctx, next_change, now,
                                              warn_pwd_expire,
-                                             already_expired)) {
+                                             already_expired,
+                                             change_pwd)) {
                return;
        }
 
@@ -927,7 +1023,8 @@ static void _pam_warn_password_expiry(struct pwb_context *ctx,
 
        if (_pam_send_password_expiry_message(ctx, next_change, now,
                                              warn_pwd_expire,
-                                             already_expired)) {
+                                             already_expired,
+                                             change_pwd)) {
                return;
        }
 
@@ -1040,6 +1137,7 @@ static bool winbind_name_list_to_sid_string_list(struct pwb_context *ctx,
        char *current_name = NULL;
        const char *search_location;
        const char *comma;
+       int len;
 
        if (sid_list_buffer_size > 0) {
                sid_list_buffer[0] = 0;
@@ -1095,6 +1193,17 @@ static bool winbind_name_list_to_sid_string_list(struct pwb_context *ctx,
                _make_remark_format(ctx, PAM_TEXT_INFO, _("Cannot convert group %s "
                                "to sid, please contact your administrator to see "
                                "if group %s is valid."), search_location, search_location);
+               /*
+                * The lookup of the last name failed..
+                * It results in require_member_of_sid ends with ','
+                * It is malformated parameter here, overwrite the last ','.
+                */
+               len = strlen(sid_list_buffer);
+               if (len) {
+                       if (sid_list_buffer[len - 1] == ',') {
+                               sid_list_buffer[len - 1] = '\0';
+                       }
+               }
        }
 
        result = true;
@@ -1744,11 +1853,13 @@ static int winbind_auth_request(struct pwb_context *ctx,
        if ((ret == PAM_SUCCESS) && user_info && policy && info) {
 
                bool already_expired = false;
+               bool change_pwd = false;
 
                /* warn a user if the password is about to expire soon */
                _pam_warn_password_expiry(ctx, user_info, policy,
                                          warn_pwd_expire,
-                                         &already_expired);
+                                         &already_expired,
+                                         &change_pwd);
 
                if (already_expired == true) {
 
@@ -1758,15 +1869,20 @@ static int winbind_auth_request(struct pwb_context *ctx,
                                       "Password has expired "
                                       "(Password was last set: %lld, "
                                       "the policy says it should expire here "
-                                      "%lld (now it's: %lu))\n",
+                                      "%lld (now it's: %ld))\n",
                                       (long long int)last_set,
                                       (long long int)last_set +
                                       policy->expire,
-                                      time(NULL));
+                                      (long)time(NULL));
 
                        return PAM_AUTHTOK_EXPIRED;
                }
 
+               if (change_pwd) {
+                       ret = PAM_NEW_AUTHTOK_REQD;
+                       goto done;
+               }
+
                /* inform about logon type */
                _pam_warn_logon_type(ctx, user, user_info->user_flags);
 
@@ -1788,7 +1904,7 @@ static int winbind_auth_request(struct pwb_context *ctx,
        if (logon.blobs) {
                wbcFreeMemory(logon.blobs);
        }
-       if (info && info->blobs) {
+       if (info && info->blobs && !p_info) {
                wbcFreeMemory(info->blobs);
        }
        if (error && !p_error) {
@@ -2174,7 +2290,7 @@ static const char *get_conf_item_string(struct pwb_context *ctx,
                        goto out;
                }
 
-               parm_opt = iniparser_getstr(ctx->dict, key);
+               parm_opt = iniparser_getstring,(ctx->dict, key, NULL);
                TALLOC_FREE(key);
 
                _pam_log_debug(ctx, LOG_INFO, "CONFIG file: %s '%s'\n",
@@ -3123,7 +3239,7 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
                                 * expire soon */
                                _pam_warn_password_expiry(ctx, user_info, policy,
                                                          warn_pwd_expire,
-                                                         NULL);
+                                                         NULL, NULL);
 
                                /* set some info3 info for other modules in the
                                 * stack */
@@ -3141,10 +3257,14 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
                                        free(username_ret);
                                }
 
-                               wbcFreeMemory(info);
-                               wbcFreeMemory(policy);
                        }
 
+                       if (info && info->blobs) {
+                               wbcFreeMemory(info->blobs);
+                       }
+                       wbcFreeMemory(info);
+                       wbcFreeMemory(policy);
+
                        goto out;
                }
        } else {