]> git.samba.org - sfrench/samba-autobuild/.git/commitdiff
Merge from TNG branch.
authorTim Potter <tpot@samba.org>
Fri, 4 May 2001 00:43:20 +0000 (00:43 +0000)
committerTim Potter <tpot@samba.org>
Fri, 4 May 2001 00:43:20 +0000 (00:43 +0000)
(This used to be commit 1e7b1c71b9c409859bcf0aeb3d5785acc4aee027)

source3/nsswitch/pam_winbind.c

index ece504411b35b6f550eac34faff54b4d6f4fb3d9..b3dea202c2c5efd04c2c5b03a308ae581ca87d44 100644 (file)
@@ -5,29 +5,7 @@
    largely based on pam_userdb by Christian Gafton <gafton@redhat.com> 
 */
 
-#include <features.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <syslog.h>
-#include <stdarg.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <errno.h>
-
-#define MODULE_NAME "pam_winbind"
-#define PAM_SM_AUTH
-#define PAM_SM_ACCOUNT
-#include <security/pam_modules.h>
-#include <security/_pam_macros.h>
-
-#define PAM_DEBUG_ARG (1<<0)
-#define PAM_USE_AUTHTOK_ARG (1<<1)
-#define PAM_UNKNOWN_OK_ARG (1<<2)
-
-#include "winbind_nss_config.h"
-#include "winbindd_nss.h"
+#include "pam_winbind.h"
 
 /* prototypes from common.c */
 void init_request(struct winbindd_request *req,int rq_type);
@@ -69,38 +47,78 @@ static int _pam_parse(int argc, const char **argv)
      return ctrl;
 }
 
-
-/* talk to winbindd */
-static int winbind_request(int req_type, const char *user, const char *pass)
+static int winbind_request(enum winbindd_cmd req_type,
+                           struct winbindd_request *request,
+                           struct winbindd_response *response)
 {
-       struct winbindd_request request;
-       struct winbindd_response response;
-
-       ZERO_STRUCT(request);
-
-       strncpy(request.data.auth.user, user, sizeof(request.data.auth.user)-1);
-       strncpy(request.data.auth.pass, pass, sizeof(request.data.auth.pass)-1);
-       
        /* Fill in request and send down pipe */
-       init_request(&request, req_type);
+       init_request(request, req_type);
        
-       if (write_sock(&request, sizeof(request)) == -1) {
+       if (write_sock(request, sizeof(*request)) == -1) {
                return -2;
        }
        
        /* Wait for reply */
-       if (read_reply(&response) == -1) {
+       if (read_reply(response) == -1) {
                return -2;
        }
 
        /* Copy reply data from socket */
-       if (response.result != WINBINDD_OK) {
+       if (response->result != WINBINDD_OK) {
                return 1;
        }
        
        return 0;
 }
 
+/* talk to winbindd */
+static int winbind_auth_request(const char *user, const char *pass)
+{
+       struct winbindd_request request;
+       struct winbindd_response response;
+
+       ZERO_STRUCT(request);
+
+       strncpy(request.data.auth.user, user, 
+                sizeof(request.data.auth.user)-1);
+
+       strncpy(request.data.auth.pass, pass, 
+                sizeof(request.data.auth.pass)-1);
+       
+        return winbind_request(WINBINDD_PAM_AUTH, &request, &response);
+}
+
+/* talk to winbindd */
+static int winbind_chauthtok_request(const char *user, const char *oldpass,
+                                     const char *newpass)
+{
+       struct winbindd_request request;
+       struct winbindd_response response;
+
+       ZERO_STRUCT(request);
+
+        if (request.data.chauthtok.user == NULL) return -2;
+
+       strncpy(request.data.chauthtok.user, user, 
+                sizeof(request.data.chauthtok.user) - 1);
+
+        if (oldpass != NULL) {
+            strncpy(request.data.chauthtok.oldpass, oldpass, 
+                    sizeof(request.data.chauthtok.oldpass) - 1);
+        } else {
+            request.data.chauthtok.oldpass[0] = '\0';
+        }
+       
+        if (newpass != NULL) {
+            strncpy(request.data.chauthtok.newpass, newpass, 
+                    sizeof(request.data.chauthtok.newpass) - 1);
+        } else {
+            request.data.chauthtok.newpass[0] = '\0';
+        }
+       
+        return winbind_request(WINBINDD_PAM_CHAUTHTOK, &request, &response);
+}
+
 /*
  * Looks up an user name and checks the password
  *
@@ -112,7 +130,7 @@ static int winbind_request(int req_type, const char *user, const char *pass)
  */
 static int user_lookup(const char *user, const char *pass)
 {
-       return winbind_request(WINBINDD_PAM_AUTH, user, pass);
+       return winbind_auth_request(user, pass);
 }
 
 /*
@@ -131,11 +149,9 @@ static int valid_user(const char *user)
 
 /* --- authentication management functions --- */
 
-/*
- * dummy conversation function sending exactly one prompt
- * and expecting exactly one response from the other party
- */
-static int converse(pam_handle_t *pamh,
+/* Attempt a conversation */
+
+static int converse(pam_handle_t *pamh, int nargs,
                    struct pam_message **message,
                    struct pam_response **response)
 {
@@ -143,9 +159,10 @@ static int converse(pam_handle_t *pamh,
     struct pam_conv *conv;
 
     retval = pam_get_item(pamh, PAM_CONV, (const void **) &conv ) ;
-    if (retval == PAM_SUCCESS)
-       retval = conv->conv(1, (const struct pam_message **)message,
+    if (retval == PAM_SUCCESS) {
+       retval = conv->conv(nargs, (const struct pam_message **)message,
                            response, conv->appdata_ptr);
+    }
        
     return retval; /* propagate error status */
 }
@@ -161,20 +178,20 @@ static char *_pam_delete(register char *xx)
 /*
  * This is a conversation function to obtain the user's password
  */
-static int conversation(pam_handle_t *pamh)
+static int auth_conversation(pam_handle_t *pamh)
 {
-    struct pam_message msg[2],*pmsg[2];
+    struct pam_message msg, *pmsg;
     struct pam_response *resp;
     int retval;
-    char * token;
+    char * token = NULL;
     
-    pmsg[0] = &msg[0];
-    msg[0].msg_style = PAM_PROMPT_ECHO_OFF;
-    msg[0].msg = "Password: ";
+    pmsg = &msg;
+    msg.msg_style = PAM_PROMPT_ECHO_OFF;
+    msg.msg = "Password: ";
 
     /* so call the conversation expecting i responses */
     resp = NULL;
-    retval = converse(pamh, pmsg, &resp);
+    retval = converse(pamh, 1, &pmsg, &resp);
 
     if (resp != NULL) {
        char * const item;
@@ -203,7 +220,6 @@ static int conversation(pam_handle_t *pamh)
     return retval;
 }
 
-
 PAM_EXTERN
 int pam_sm_authenticate(pam_handle_t *pamh, int flags,
                        int argc, const char **argv)
@@ -225,7 +241,7 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags,
      
      if ((ctrl & PAM_USE_AUTHTOK_ARG) == 0) {
         /* Converse just to be sure we have the password */
-        retval = conversation(pamh);
+        retval = auth_conversation(pamh);
         if (retval != PAM_SUCCESS) {
             _pam_log(LOG_ERR, "could not obtain password for `%s'",
                      username);
@@ -336,24 +352,134 @@ int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags,
 }
 
 
+PAM_EXTERN
+int pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, 
+                     const char **argv)
+{
+    int retval;
+    char *newpw, *oldpw;
+    const char *user;
+
+    /* Get name of a user */
+
+    retval = pam_get_user(pamh, &user, "Username: ");
+
+    if (retval != PAM_SUCCESS) {
+        return retval;
+    }
+
+    /* XXX check in domain format */
+
+    /* Perform preliminary check and store requested password for updating
+       later on */
+
+    if (flags & PAM_PRELIM_CHECK) {
+        struct pam_message msg[3], *pmsg[3];
+        struct pam_response *resp;
+
+        /* Converse to ensure we have the current password */
+
+        retval = auth_conversation(pamh);
+
+        if (retval != PAM_SUCCESS) {
+            return retval;
+        }
+
+        /* Obtain and verify current password */
+
+        pmsg[0] = &msg[0];
+        msg[0].msg_style = PAM_TEXT_INFO;
+        msg[0].msg = "Changing password for user %s";
+
+        pmsg[1] = &msg[1];
+        msg[1].msg_style = PAM_PROMPT_ECHO_OFF;
+        msg[1].msg = "New NT password: ";
+
+        pmsg[2] = &msg[2];
+        msg[2].msg_style = PAM_PROMPT_ECHO_OFF;
+        msg[2].msg = "Retype new NT password: ";
+
+        resp = NULL;
+
+        retval = converse(pamh, 3, pmsg, &resp);
+
+        if (resp != NULL) {
+
+            if (retval == PAM_SUCCESS) {
+
+                /* Check password entered correctly */
+
+                if (strcmp(resp[1].resp, resp[2].resp) != 0) { 
+                    struct pam_response *resp2;
+
+                    msg[0].msg_style = PAM_ERROR_MSG;
+                    msg[0].msg = "Sorry, passwords do not match";
+
+                    converse(pamh, 1, pmsg, &resp2);
+
+                    _pam_drop_reply(resp, 3);
+                    _pam_drop_reply(resp2, 1);
+
+                    return PAM_AUTHTOK_RECOVER_ERR;
+                }
+
+                /* Store passwords */
+
+                retval = pam_set_item(pamh, PAM_OLDAUTHTOK, resp[1].resp);
+                _pam_drop_reply(resp, 3);
+            }
+        }
+
+        /* XXX What happens if root? */
+        /* XXX try first pass and use first pass args */
+
+        return retval;
+    }
+
+    if (flags & PAM_UPDATE_AUTHTOK) {
+
+        retval = pam_get_item(pamh, PAM_OLDAUTHTOK, (const void **)&newpw);
+        if (retval != PAM_SUCCESS) {
+            return PAM_AUTHTOK_ERR;
+        }
+
+        retval = pam_get_item(pamh, PAM_AUTHTOK, (const void **)&oldpw);
+        if (retval != PAM_SUCCESS) {
+            return PAM_AUTHTOK_ERR;
+        }
+
+        fprintf(stderr, "oldpw = %s, newpw = %s\n", oldpw, newpw);
+
+        if (retval == PAM_SUCCESS && 
+            winbind_chauthtok_request(user, oldpw, newpw) == 0) {
+            return PAM_SUCCESS;
+        }
+
+        return PAM_AUTHTOK_ERR;
+    }
+
+    return PAM_SERVICE_ERR;
+}
+
 #ifdef PAM_STATIC
 
 /* static module data */
 
-struct pam_module _pam_userdb_modstruct = {
+struct pam_module _pam_winbind_modstruct = {
      MODULE_NAME,
      pam_sm_authenticate,
      pam_sm_setcred,
      pam_sm_acct_mgmt,
      NULL,
      NULL,
-     NULL,
+     pam_sm_chauthtok
 };
 
 #endif
 
 /*
  * Copyright (c) Andrew Tridgell <tridge@samba.org> 2000
+ * Copyright (c) Tim Potter      <tpot@samba.org>   2000
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions