]> arthur.barton.de Git - netatalk.git/blobdiff - etc/uams/uams_dhx2_pam.c
Merge master
[netatalk.git] / etc / uams / uams_dhx2_pam.c
index f2976b45fb83d24af1edd6e32577a6bc876315dd..0f0c8a535329b579bac63659a88b41194f481b59 100644 (file)
@@ -529,16 +529,46 @@ exit:
     return ret;
 }
 
-static int logincont2(void *obj, struct passwd **uam_pwd,
+/**
+ * Try to authenticate via PAM as "adminauthuser"
+ **/
+static int loginasroot(const char *adminauthuser, const char **hostname, int status)
+{
+    int PAM_error;
+
+    if ((PAM_error = pam_end(pamh, status)) != PAM_SUCCESS)
+        goto exit;
+    pamh = NULL;
+
+    if ((PAM_error = pam_start("netatalk", adminauthuser, &PAM_conversation, &pamh)) != PAM_SUCCESS) {
+        LOG(log_info, logtype_uams, "DHX2: PAM_Error: %s", pam_strerror(pamh,PAM_error));
+        goto exit;
+    }
+
+    /* solaris craps out if PAM_TTY and PAM_RHOST aren't set. */
+    pam_set_item(pamh, PAM_TTY, "afpd");
+    pam_set_item(pamh, PAM_RHOST, *hostname);
+    if ((PAM_error = pam_authenticate(pamh, 0)) != PAM_SUCCESS)
+        goto exit;
+
+    LOG(log_warning, logtype_uams, "DHX2: Authenticated as \"%s\"", adminauthuser);
+
+exit:
+    return PAM_error;
+}
+
+static int logincont2(void *obj_in, struct passwd **uam_pwd,
                       char *ibuf, size_t ibuflen,
                       char *rbuf _U_, size_t *rbuflen)
 {
-    int ret;
+    AFPObj *obj = obj_in;
+    int ret = AFPERR_MISC;
     int PAM_error;
     const char *hostname = NULL;
     gcry_mpi_t retServerNonce;
     gcry_cipher_hd_t ctx;
     gcry_error_t ctxerror;
+    char *utfpass = NULL;
 
     *rbuflen = 0;
 
@@ -594,27 +624,41 @@ static int logincont2(void *obj, struct passwd **uam_pwd,
 
     /* ---- Start authentication with PAM --- */
 
+    /* The password is in legacy Mac encoding, convert it to host encoding */
+    if (convert_string_allocate(CH_MAC, CH_UNIX, ibuf, -1, &utfpass) == (size_t)-1) {
+        LOG(log_error, logtype_uams, "DHX2: conversion error");
+        goto error_ctx;
+    }
+    PAM_password = utfpass;
+
+#ifdef DEBUG
+    LOG(log_maxdebug, logtype_default, "DHX2: password: %s", PAM_password);
+#endif
+
     /* Set these things up for the conv function */
-    PAM_password = ibuf;
 
     ret = AFPERR_NOTAUTH;
     PAM_error = pam_start("netatalk", PAM_username, &PAM_conversation, &pamh);
     if (PAM_error != PAM_SUCCESS) {
-        LOG(log_info, logtype_uams, "DHX2: PAM_Error: %s",
-            pam_strerror(pamh,PAM_error));
+        LOG(log_info, logtype_uams, "DHX2: PAM_Error: %s", pam_strerror(pamh,PAM_error));
         goto error_ctx;
     }
 
     /* solaris craps out if PAM_TTY and PAM_RHOST aren't set. */
     pam_set_item(pamh, PAM_TTY, "afpd");
     pam_set_item(pamh, PAM_RHOST, hostname);
+
     PAM_error = pam_authenticate(pamh, 0);
     if (PAM_error != PAM_SUCCESS) {
         if (PAM_error == PAM_MAXTRIES)
             ret = AFPERR_PWDEXPR;
-        LOG(log_info, logtype_uams, "DHX2: PAM_Error: %s",
-            pam_strerror(pamh, PAM_error));
-        goto error_ctx;
+        LOG(log_info, logtype_uams, "DHX2: PAM_Error: %s", pam_strerror(pamh, PAM_error));
+
+        if (!obj->options.adminauthuser)
+            goto error_ctx;
+        if (loginasroot(obj->options.adminauthuser, &hostname, PAM_error) != PAM_SUCCESS) {
+            goto error_ctx;
+        }
     }
 
     PAM_error = pam_acct_mgmt(pamh, 0);
@@ -627,8 +671,7 @@ static int logincont2(void *obj, struct passwd **uam_pwd,
         else if (PAM_error == PAM_AUTHTOKEN_REQD)
             ret = AFPERR_PWDCHNG;
 #endif
-        else
-            goto error_ctx;
+        goto error_ctx;
     }
 
 #ifndef PAM_CRED_ESTABLISH
@@ -649,15 +692,17 @@ static int logincont2(void *obj, struct passwd **uam_pwd,
     }
 
     memset(ibuf, 0, 256); /* zero out the password */
+    if (utfpass)
+        memset(utfpass, 0, strlen(utfpass));
     *uam_pwd = dhxpwd;
     LOG(log_info, logtype_uams, "DHX2: PAM Auth OK!");
-    if ( ret == AFPERR_PWDEXPR)
-        return ret;
+
     ret = AFP_OK;
 
 error_ctx:
     gcry_cipher_close(ctx);
 error_noctx:
+    if (utfpass) free(utfpass);
     free(K_MD5hash);
     K_MD5hash=NULL;
     gcry_mpi_release(serverNonce);