]> arthur.barton.de Git - netatalk.git/blobdiff - etc/uams/uams_dhx2_pam.c
Merge remote-tracking branch 'origin/branch-netatalk-3-0' into develop
[netatalk.git] / etc / uams / uams_dhx2_pam.c
index 46c0d9700b7248fae5a424dd52d9109135dfdd29..8e79b450d4c802e9e6e516c598c2ced645270476 100644 (file)
@@ -32,7 +32,7 @@
 
 #include <atalk/afp.h>
 #include <atalk/uam.h>
-#include "../afpd/globals.h"
+#include <atalk/globals.h>
 
 /* Number of bits for p which we generate. Everybode out there uses 512, so we beet them */
 #define PRIMEBITS 1024
@@ -46,7 +46,7 @@ static gcry_mpi_t p, g, Ra;
 static gcry_mpi_t serverNonce;
 static char *K_MD5hash = NULL;
 static int K_hash_len;
-static u_int16_t ID;
+static uint16_t ID;
 
 /* The initialization vectors for CAST128 are fixed by Apple. */
 static unsigned char dhx_c2siv[] = { 'L', 'W', 'a', 'l', 'l', 'a', 'c', 'e' };
@@ -136,7 +136,11 @@ error:
  * echo off means password.
  */
 static int PAM_conv (int num_msg,
+#ifdef LINUX
                      const struct pam_message **msg,
+#else
+                     struct pam_message **msg,
+#endif
                      struct pam_response **resp,
                      void *appdata_ptr _U_) {
     int count = 0;
@@ -242,6 +246,7 @@ static int dhx2_setup(void *obj, char *ibuf _U_, size_t ibuflen _U_,
     size_t nwritten;
     gcry_mpi_t Ma;
     char *Ra_binary = NULL;
+    uint16_t uint16;
 
     *rbuflen = 0;
 
@@ -267,7 +272,8 @@ static int dhx2_setup(void *obj, char *ibuf _U_, size_t ibuflen _U_,
 
     /* Session ID first */
     ID = dhxhash(obj);
-    *(u_int16_t *)rbuf = htons(ID);
+    uint16 = htons(ID);
+    memcpy(rbuf, &uint16, sizeof(uint16_t));
     rbuf += 2;
     *rbuflen += 2;
 
@@ -281,7 +287,9 @@ static int dhx2_setup(void *obj, char *ibuf _U_, size_t ibuflen _U_,
     *rbuflen += 4;
 
     /* len = length of p = PRIMEBITS/8 */
-    *(u_int16_t *)rbuf = htons((u_int16_t) PRIMEBITS/8);
+
+    uint16 = htons((uint16_t) PRIMEBITS/8);
+    memcpy(rbuf, &uint16, sizeof(uint16_t));
     rbuf += 2;
     *rbuflen += 2;
 
@@ -365,7 +373,7 @@ static int pam_login_ext(void *obj, char *uname, struct passwd **uam_pwd,
 {
     char *username;
     size_t len, ulen;
-    u_int16_t  temp16;
+    uint16_t  temp16;
 
     *rbuflen = 0;
 
@@ -403,6 +411,7 @@ static int logincont1(void *obj _U_, char *ibuf, size_t ibuflen, char *rbuf, siz
     char serverNonce_bin[16];
     gcry_cipher_hd_t ctx;
     gcry_error_t ctxerror;
+    uint16_t uint16;
 
     *rbuflen = 0;
 
@@ -488,7 +497,8 @@ static int logincont1(void *obj _U_, char *ibuf, size_t ibuflen, char *rbuf, siz
     /* ---- Start building reply packet ---- */
 
     /* Session ID + 1 first */
-    *(u_int16_t *)rbuf = htons(ID+1);
+    uint16 = htons(ID+1);
+    memcpy(rbuf, &uint16, sizeof(uint16_t));
     rbuf += 2;
     *rbuflen += 2;
 
@@ -529,16 +539,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 +634,42 @@ 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_set_item(pamh, PAM_RUSER, PAM_username);
+
     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 +682,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 +703,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);
@@ -669,11 +725,12 @@ static int pam_logincont(void *obj, struct passwd **uam_pwd,
                          char *ibuf, size_t ibuflen,
                          char *rbuf, size_t *rbuflen)
 {
-    u_int16_t retID;
+    uint16_t retID;
     int ret;
 
     /* check for session id */
-    retID = ntohs(*(u_int16_t *)ibuf);
+    memcpy(&retID, ibuf, sizeof(uint16_t));
+    retID = ntohs(retID);
     if (retID == ID)
         ret = logincont1(obj, ibuf, ibuflen, rbuf, rbuflen);
     else if (retID == ID+1)
@@ -866,7 +923,7 @@ static int dhx2_changepw(void *obj _U_, char *uname,
     return ret;
 }
 
-static int uam_setup(const char *path)
+static int uam_setup(void *obj, const char *path)
 {
     if (uam_register(UAM_SERVER_LOGIN_EXT, path, "DHX2", pam_login,
                      pam_logincont, pam_logout, pam_login_ext) < 0)
@@ -874,9 +931,6 @@ static int uam_setup(const char *path)
     if (uam_register(UAM_SERVER_CHANGEPW, path, "DHX2", dhx2_changepw) < 0)
         return -1;
 
-    p = gcry_mpi_new(0);
-    g = gcry_mpi_new(0);
-
     LOG(log_debug, logtype_uams, "DHX2: generating mersenne primes");
     /* Generate p and g for DH */
     if (dh_params_generate(PRIMEBITS) != 0) {
@@ -892,11 +946,12 @@ static void uam_cleanup(void)
     uam_unregister(UAM_SERVER_LOGIN, "DHX2");
     uam_unregister(UAM_SERVER_CHANGEPW, "DHX2");
 
+    LOG(log_debug, logtype_uams, "DHX2: uam_cleanup");
+
     gcry_mpi_release(p);
     gcry_mpi_release(g);
 }
 
-
 UAM_MODULE_EXPORT struct uam_export uams_dhx2 = {
     UAM_MODULE_SERVER,
     UAM_MODULE_VERSION,