]> arthur.barton.de Git - netatalk.git/commitdiff
Sam's bug fix in the AFP connection negotiation stage and his preliminary
authorsrittau <srittau>
Mon, 9 Jun 2003 14:30:42 +0000 (14:30 +0000)
committersrittau <srittau>
Mon, 9 Jun 2003 14:30:42 +0000 (14:30 +0000)
support for an Kerberos 5 UAM.

NEWS
etc/afpd/afp_options.c
etc/afpd/globals.h
etc/afpd/status.c
etc/afpd/status.h
etc/afpd/uam.c

diff --git a/NEWS b/NEWS
index 8890ca33e41244f6d1e13cc9c49e1fedd1f04c7e..3ee7a52fae5297f723463f35d715b5e973c6de9d 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,9 @@
 Changes in 1.6.3
 ================
 
+* UPD: afpd: Infrastructural support for an upcoming Kerberos 5 UAM.
+       [Sam Noble]
+* FIX: afpd: Bug in AFP connection negotiation stage. [Sam]
 * FIX: afpd: Catsearch, when Mac and unix name differ, search on attributes.
 * FIX: afpd: Files could be opened for writing on read-only filesystems.
 * FIX: afpd: Debugging using SIGUSR1 was broken. [Stefan Muenkner]
index f56b7ea1ec9f1153a0a934003eced527d6433f34..eff24a7f63573aeb52f84df49d12c0031d653a03 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: afp_options.c,v 1.27 2002-08-24 05:00:07 sibaz Exp $
+ * $Id: afp_options.c,v 1.27.2.1 2003-06-09 14:30:43 srittau Exp $
  *
  * Copyright (c) 1997 Adrian Sun (asun@zoology.washington.edu)
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
@@ -122,6 +122,10 @@ void afp_options_free(struct afp_options *opt,
         free(opt->nlspath);
     if (opt->passwdfile && (opt->passwdfile != save->passwdfile))
         free(opt->passwdfile);
+    if (opt->k5service && (opt->k5service != save->k5service))
+        free(opt->k5service);
+    if (opt->k5realm && (opt->k5realm != save->k5realm))
+        free(opt->k5realm);
 }
 
 /* initialize options */
@@ -148,6 +152,8 @@ void afp_options_init(struct afp_options *options)
 #ifdef ADMIN_GRP
     options->admingid = 0;
 #endif /* ADMIN_GRP */
+    options->k5service = NULL;
+    options->k5realm = NULL;
 }
 
 /* parse an afpd.conf line. i'm doing it this way because it's
@@ -371,6 +377,12 @@ int afp_options_parseline(char *buf, struct afp_options *options)
     }
 #endif /* ADMIN_GRP */
 
+    if ((c = getoption(buf, "-k5service")) && (opt = strdup(c)))
+        options->k5service = opt;
+    if ((c = getoption(buf, "-k5realm")) && (opt = strdup(c)))
+        options->k5realm = opt;
+    if ((c = getoption(buf, "-k5keytab")))
+        setenv( "KRB5_KTNAME", c, 1 );
     if ((c = getoption(buf, "-authprintdir")) && (opt = strdup(c)))
         options->authprintdir = opt;
     if ((c = getoption(buf, "-uampath")) && (opt = strdup(c)))
index 65ab4f77ab641a0a2cd24d1d84e803bf03b1ca82..7ec61aa1e1334ae38f848507c8d8635a6dd03a30 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: globals.h,v 1.14 2002-08-31 05:35:10 jmarcus Exp $
+ * $Id: globals.h,v 1.14.2.1 2003-06-09 14:30:44 srittau Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -59,6 +59,7 @@ struct afp_options {
     char *guest, *loginmesg, *keyfile, *passwdfile;
     char *uamlist;
     char *authprintdir;
+    char *k5service, *k5realm;
     mode_t umask;
     mode_t save_mask;
 #ifdef ADMIN_GRP
index f5acacaeb4c59245199c57b58048c4f05d278ca3..e90af43c6241c5c0c732fd291e190ad2dfbc0fbd 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: status.c,v 1.7 2002-02-06 21:58:50 jmarcus Exp $
+ * $Id: status.c,v 1.7.4.1 2003-06-09 14:30:45 srittau Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -35,7 +35,7 @@
 #include "icon.h"
 
 static void status_flags(char *data, const int notif, const int ipok,
-                         const unsigned char passwdbits)
+                         const unsigned char passwdbits, const int dirsrvcs)
 {
     u_int16_t           status;
 
@@ -58,6 +58,8 @@ static void status_flags(char *data, const int notif, const int ipok,
         status |= AFPSRVRINFO_SRVNOTIFY;
     }
     status |= AFPSRVRINFO_FASTBOZO;
+    if (dirsrvcs)
+       status |= AFPSRVRINFO_SRVRDIR;
     status = htons(status);
     memcpy(data + AFPSTATUS_FLAGOFF, &status, sizeof(status));
 }
@@ -82,14 +84,18 @@ static int status_server(char *data, const char *server)
         len++;
     data += len;
 
-    /* make room for signature and net address offset. save location of
-     * signature offset. 
+    /* Make room for signature and net address offset. Save location of
+     * signature offset. We're also making room for directory names offset
+     * and the utf-8 server name offset.
      *
-     * NOTE: technically, we don't need to reserve space for the
+     * NOTE: Technically, we don't need to reserve space for the
      * signature and net address offsets if they're not going to be
-     * used. as there are no offsets after them, it doesn't hurt to
-     * have them specified though. so, we just do that to simplify
-     * things.  
+     * used. As there are no offsets after them, it doesn't hurt to
+     * have them specified though. So, we just do that to simplify
+     * things.
+     *
+     * NOTE2: AFP3.1 Documentation states that the directory names offset
+     * is a required feature, even though it can be set to zero.
      */
     len = data - start;
     status = htons(len + AFPSTATUS_POSTLEN);
@@ -179,7 +185,7 @@ static u_int16_t status_signature(char *data, int *servoffset, DSI *dsi,
     return sigoff;
 }
 
-static int status_netaddress(char *data, const int servoffset,
+static int status_netaddress(char *data, int *servoffset,
                              const ASP asp, const DSI *dsi,
                              const char *fqdn)
 {
@@ -189,7 +195,7 @@ static int status_netaddress(char *data, const int servoffset,
     begin = data;
 
     /* get net address offset */
-    memcpy(&offset, data + servoffset, sizeof(offset));
+    memcpy(&offset, data + *servoffset, sizeof(offset));
     data += ntohs(offset);
 
     /* format:
@@ -203,12 +209,12 @@ static int status_netaddress(char *data, const int servoffset,
     /* number of addresses. this currently screws up if we have a dsi
        connection, but we don't have the ip address. to get around this,
        we turn off the status flag for tcp/ip. */
-    *data++ = (fqdn ? 1 : 0) + (dsi ? 1 : 0) + (asp ? 1 : 0);
+    *data++ = ((fqdn && dsi) ? 1 : 0) + (dsi ? 1 : 0) + (asp ? 1 : 0);
 
     /* handle DNS names */
-    if (fqdn) {
-        int len = strlen(fqdn) + 2;
-        *data++ = len;
+    if (fqdn && dsi) {
+        int len = strlen(fqdn);
+        *data++ = len + 2;
         *data++ = 0x04;
         memcpy(data, fqdn, len);
         data += len;
@@ -253,6 +259,85 @@ static int status_netaddress(char *data, const int servoffset,
     }
 #endif /* ! NO_DDP */
 
+    /* calculate/store Directory Services Names offset */
+    offset = htons(data - begin);
+    *servoffset += sizeof(offset);
+    memcpy(begin + *servoffset, &offset, sizeof(offset));
+
+    /* return length of buffer */
+    return (data - begin);
+}
+
+static int status_directorynames(char *data, int *diroffset,
+                                const DSI *dsi,
+                                const struct afp_options *options)
+{
+    char *begin = data;
+    u_int16_t offset;
+    memcpy(&offset, data + *diroffset, sizeof(offset));
+    offset = ntohs(offset);
+    data += offset;
+                                                                                
+    /* I can not find documentation of any other purpose for the
+     * DirectoryNames field.
+     */
+    /*
+     * Try to synthesize a principal:
+     * service '/' fqdn '@' realm
+     */
+    if (options->k5service && options->k5realm && options->fqdn) {
+       /* should k5princ be utf8 encoded? */
+       u_int8_t len;
+       char *p = strchr( options->fqdn, ':' );
+       if (p)
+           *p = '\0';
+       len = strlen( options->k5service )
+                       + strlen( options->fqdn )
+                       + strlen( options->k5realm );
+       len+=2; /* '/' and '@' */
+       *data++ = 1; /* DirectoryNamesCount */
+       *data++ = len;
+       snprintf( data, len + 1, "%s/%s@%s", options->k5service,
+                               options->fqdn, options->k5realm );
+       data += len;
+       if (p)
+            *p = ':';
+    } else {
+       memset(begin + *diroffset, 0, sizeof(offset));
+    }
+
+    /* Calculate and store offset for UTF8ServerName */
+    *diroffset += sizeof(u_int16_t);
+    offset = htons(data - begin);
+    memcpy(begin + *diroffset, &offset, sizeof(u_int16_t));
+                                                                                
+    /* return length of buffer */
+    return (data - begin);
+}
+
+static int status_utf8servername(char *data, int *nameoffset,
+                                const DSI *dsi,
+                                const struct afp_options *options)
+{
+    u_int16_t namelen, len;
+    char *begin = data;
+    u_int16_t offset;
+    memcpy(&offset, data + *nameoffset, sizeof(offset));
+    offset = ntohs(offset);
+    data += offset;
+                                                                                
+    /* FIXME: For now we set the UTF-8 ServerName offset to 0
+     * It's irrelevent anyway until we set the appropriate Flags value.
+     * Later this can be set to something meaningful.
+     *
+     * What is the valid character range for an nbpname?
+     *
+     * Apple's server likes to use the non-qualified hostname
+     * This obviously won't work very well if multiple servers are running
+     * on the box.
+     */
+    memset(begin + *nameoffset, 0, sizeof(offset));
+                                                                                
     /* return length of buffer */
     return (data - begin);
 }
@@ -287,7 +372,7 @@ void status_init(AFPConfig *aspconfig, AFPConfig *dsiconfig,
     ASP asp;
     DSI *dsi;
     char *status;
-    int c, sigoff;
+    int statuslen, c, sigoff;
 
     if (!(aspconfig || dsiconfig) || !options)
         return;
@@ -327,7 +412,8 @@ void status_init(AFPConfig *aspconfig, AFPConfig *dsiconfig,
 
     status_flags(status, options->server_notif, options->fqdn ||
                  (dsiconfig && dsi->server.sin_addr.s_addr),
-                 options->passwdbits);
+                 options->passwdbits,
+                 (options->k5service && options->k5realm && options->fqdn));
     /* returns offset to signature offset */
     c = status_server(status, options->server ? options->server :
                       options->hostname);
@@ -340,16 +426,21 @@ void status_init(AFPConfig *aspconfig, AFPConfig *dsiconfig,
         status_icon(status, apple_atalk_icon, sizeof(apple_atalk_icon), c);
 
     sigoff = status_signature(status, &c, dsi, options->hostname);
+    /* c now contains the offset where the netaddress offset lives */
+                                                                                
+    status_netaddress(status, &c, asp, dsi, options->fqdn);
+    /* c now contains the offset where the Directory Names Count offset lives */                                                                                
+    status_directorynames(status, &c, dsi, options);
+    /* c now contains the offset where the UTF-8 ServerName offset lives */
 
-    /* returns length */
-    c = status_netaddress(status, c, asp, dsi, options->fqdn);
+    statuslen = status_utf8servername(status, &c, dsi, options);
 
 
 #ifndef NO_DDP
     if (aspconfig) {
-        asp_setstatus(asp, status, c);
+        asp_setstatus(asp, status, statuslen);
         aspconfig->signature = status + sigoff;
-        aspconfig->statuslen = c;
+        aspconfig->statuslen = statuslen;
     }
 #endif /* ! NO_DDP */
 
@@ -362,9 +453,9 @@ void status_init(AFPConfig *aspconfig, AFPConfig *dsiconfig,
         if ((options->flags & OPTION_CUSTOMICON) == 0) {
             status_icon(status, apple_tcp_icon, sizeof(apple_tcp_icon), 0);
         }
-        dsi_setstatus(dsi, status, c);
+        dsi_setstatus(dsi, status, statuslen);
         dsiconfig->signature = status + sigoff;
-        dsiconfig->statuslen = c;
+        dsiconfig->statuslen = statuslen;
     }
 }
 
index f4e984b23575c4961d18caa855c4a16bfdf06a13..307385939a2ec6a48a7def6fa8c19a3d38cb1898 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: status.h,v 1.5 2001-12-03 05:03:38 jmarcus Exp $
+ * $Id: status.h,v 1.5.4.1 2003-06-09 14:30:45 srittau Exp $
  */
 
 #ifndef AFPD_STATUS_H
 #define AFPSTATUS_UAMSOFF     4
 #define AFPSTATUS_ICONOFF     6
 #define AFPSTATUS_FLAGOFF     8
+/* AFPSTATUS_PRELEN is the number of bytes for status data prior to 
+ * the ServerName field.
+ *
+ * This is two bytes of offset space for the MachineType, AFPVersionCount,
+ * UAMCount, VolumeIconAndMask, and the 16-bit "Fixed" status flags.
+ */
 #define AFPSTATUS_PRELEN     10
-#define AFPSTATUS_POSTLEN     4
+/* AFPSTATUS_POSTLEN is the number of bytes for offset records
+ * after the ServerName field.
+ *
+ * Right now, this is 2 bytes each for ServerSignature, networkAddressCount,
+ * DirectoryNameCount, and UTF-8 ServerName
+ */
+#define AFPSTATUS_POSTLEN     8
 #define AFPSTATUS_LEN        (AFPSTATUS_PRELEN + AFPSTATUS_POSTLEN)
 
 
index 7e18ee2025d344a54e0dda709a97d8a013cbe717..400b30925dca0f6fe53051312bcb6cc9b5d3f498 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: uam.c,v 1.23 2002-10-17 18:01:54 didg Exp $
+ * $Id: uam.c,v 1.22.4.1 2003-06-09 14:30:45 srittau Exp $
  *
  * Copyright (c) 1999 Adrian Sun (asun@zoology.washington.edu)
  * All Rights Reserved.  See COPYRIGHT.
@@ -64,9 +64,6 @@ char *strchr (), *strrchr ();
 #endif /* TRU64 */
 
 /* --- server uam functions -- */
-#ifndef NO_LOAD_UAM
-extern  int uam_setup(const char *path);
-#endif
 
 /* uam_load. uams must have a uam_setup function. */
 struct uam_mod *uam_load(const char *path, const char *name)
@@ -75,12 +72,10 @@ struct uam_mod *uam_load(const char *path, const char *name)
     struct uam_mod *mod;
     void *module;
 
-#ifndef NO_LOAD_UAM
     if ((module = mod_open(path)) == NULL) {
         LOG(log_error, logtype_afpd, "uam_load(%s): failed to load: %s", name, mod_error());
         return NULL;
     }
-#endif
 
     if ((mod = (struct uam_mod *) malloc(sizeof(struct uam_mod))) == NULL) {
         LOG(log_error, logtype_afpd, "uam_load(%s): malloc failed", name);
@@ -91,8 +86,6 @@ struct uam_mod *uam_load(const char *path, const char *name)
     buf[sizeof(buf) - 1] = '\0';
     if ((p = strchr(buf, '.')))
         *p = '\0';
-
-#ifndef NO_LOAD_UAM
     if ((mod->uam_fcn = mod_symbol(module, buf)) == NULL) {
         LOG(log_error, logtype_afpd, "uam_load(%s): mod_symbol error for symbol %s",
             name,
@@ -113,9 +106,6 @@ struct uam_mod *uam_load(const char *path, const char *name)
         LOG(log_error, logtype_afpd, "uam_load(%s): uam_setup failed", name);
         goto uam_load_err;
     }
-#else
-   uam_setup(name);
-#endif
 
     mod->uam_module = module;
     return mod;
@@ -134,15 +124,12 @@ void uam_unload(struct uam_mod *mod)
 {
     if (mod->uam_fcn->uam_cleanup)
         (*mod->uam_fcn->uam_cleanup)();
-
-#ifndef NO_LOAD_UAM
     mod_close(mod->uam_module);
-#endif    
     free(mod);
 }
 
 /* -- client-side uam functions -- */
-#ifndef ATACC
+
 /* set up stuff for this uam. */
 int uam_register(const int type, const char *path, const char *name, ...)
 {
@@ -174,15 +161,7 @@ int uam_register(const int type, const char *path, const char *name, ...)
 
     va_start(ap, name);
     switch (type) {
-    case UAM_SERVER_LOGIN_EXT: /* expect four arguments */
-        uam->u.uam_login.login = va_arg(ap, void *);
-        uam->u.uam_login.logincont = va_arg(ap, void *);
-        uam->u.uam_login.logout = va_arg(ap, void *);
-        uam->u.uam_login.login_ext = va_arg(ap, void *);
-        break;
-    
     case UAM_SERVER_LOGIN: /* expect three arguments */
-        uam->u.uam_login.login_ext = NULL;
         uam->u.uam_login.login = va_arg(ap, void *);
         uam->u.uam_login.logincont = va_arg(ap, void *);
         uam->u.uam_login.logout = va_arg(ap, void *);
@@ -205,69 +184,6 @@ int uam_register(const int type, const char *path, const char *name, ...)
 
     return 0;
 }
-#endif
-
-#ifdef ATACC
-int uam_register_fn(const int type, const char *path, const char *name, void *fn1, void *fn2, 
-                     void *fn3, void *fn4)
-{
-    va_list ap;
-    struct uam_obj *uam;
-
-    if (!name)
-        return -1;
-
-    /* see if it already exists. */
-    if ((uam = auth_uamfind(type, name, strlen(name)))) {
-        if (strcmp(uam->uam_path, path)) {
-            /* it exists, but it's not the same module. */
-            LOG(log_error, logtype_afpd, "uam_register: \"%s\" already loaded by %s",
-                name, path);
-            return -1;
-        }
-        uam->uam_count++;
-        return 0;
-    }
-
-    /* allocate space for uam */
-    if ((uam = calloc(1, sizeof(struct uam_obj))) == NULL)
-        return -1;
-
-    uam->uam_name = name;
-    uam->uam_path = strdup(path);
-    uam->uam_count++;
-
-    switch (type) {
-    case UAM_SERVER_LOGIN_EXT: /* expect four arguments */
-        uam->u.uam_login.login_ext = fn4;
-        uam->u.uam_login.login = fn1;
-        uam->u.uam_login.logincont = fn2;
-        uam->u.uam_login.logout = fn3;
-        break;
-    case UAM_SERVER_LOGIN: /* expect three arguments */
-        uam->u.uam_login.login_ext = NULL;
-        uam->u.uam_login.login = fn1;
-        uam->u.uam_login.logincont = fn2;
-        uam->u.uam_login.logout = fn3;
-        break;
-    case UAM_SERVER_CHANGEPW: /* one argument */
-        uam->u.uam_changepw = fn1;
-        break;
-    case UAM_SERVER_PRINTAUTH: /* x arguments */
-    default:
-        break;
-    }
-
-    /* attach to other uams */
-    if (auth_register(type, uam) < 0) {
-        free(uam->uam_path);
-        free(uam);
-        return -1;
-    }
-
-    return 0;
-}
-#endif
 
 void uam_unregister(const int type, const char *name)
 {
@@ -466,7 +382,11 @@ AFPObj *obj = private;
          * the cookie. */
         *buf = (void *) &obj->uam_cookie;
         break;
-
+    case UAM_OPTION_KRB5SERVICE:
+        *buf = obj->options.k5service;
+        if (len)
+            *len = strlen(obj->options.k5service);
+        break;
     default:
         return -1;
         break;