]> arthur.barton.de Git - netatalk.git/commitdiff
The following were necessary in order to implement a Kerbers 5 UAM compatible
authorsamnoble <samnoble>
Wed, 16 Apr 2003 22:45:08 +0000 (22:45 +0000)
committersamnoble <samnoble>
Wed, 16 Apr 2003 22:45:08 +0000 (22:45 +0000)
with what Apple ships in OS X 10.2.

o support for specifying k5service and k5realm in afpd.conf
o support for UTF8ServerName and DirectoryServicesNames in GetStatus reply
o uam support for querying the server's k5service setting

etc/afpd/afp_options.c
etc/afpd/auth.c
etc/afpd/globals.h
etc/afpd/status.c
etc/afpd/status.h
etc/afpd/uam.c
include/atalk/uam.h

index 2e75bcc05f42a22df45b33f78285c834ee7526c0..0dabeae22dd4c7dfb2a42340cd870a233c801f1e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: afp_options.c,v 1.29 2003-01-12 14:39:57 didg Exp $
+ * $Id: afp_options.c,v 1.30 2003-04-16 22:45:08 samnoble Exp $
  *
  * Copyright (c) 1997 Adrian Sun (asun@zoology.washington.edu)
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
@@ -124,6 +124,10 @@ void afp_options_free(struct afp_options *opt,
         free(opt->passwdfile);
     if (opt->signature && (opt->signature != save->signature))
        free(opt->signature);
+    if (opt->k5service && (opt->k5service != save->k5service))
+       free(opt->k5service);
+    if (opt->k5realm && (opt->k5realm != save->k5realm))
+       free(opt->k5realm);
 }
 
 /* initialize options */
@@ -151,6 +155,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
@@ -374,6 +380,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 2ee455418fe3efb82d3d4e319cbcfda8ec3b4d12..5ef217b0b5dcf283540b2c33c69b60ba13d98021 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: auth.c,v 1.43 2003-04-14 18:11:06 didg Exp $
+ * $Id: auth.c,v 1.44 2003-04-16 22:45:10 samnoble Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -623,10 +623,12 @@ unsigned int      ibuflen, *rbuflen;
     default:
         return send_reply(obj, AFPERR_PARAM);
     }    
+#if 0
     if (len != 0) {
         LOG(log_error, logtype_afpd, "login_ext: directory service path not null!" );
         return send_reply(obj, AFPERR_PARAM);
     }
+#endif
     ibuf += len;
     ibuflen -= len;
     
@@ -636,7 +638,7 @@ unsigned int        ibuflen, *rbuflen;
         ibuflen--;
     }
 
-    /* FIXME user name are in unicode */    
+    /* FIXME user name are in UTF8 */    
     i = afp_uam->u.uam_login.login_ext(obj, username, &pwd, ibuf, ibuflen, rbuf, rbuflen);
     if (i || !pwd)
         return send_reply(obj, i);
index 986fc0e714f5cd43e7dea2c41d1e92e3cc9fb7ae..7765c895d74ace138b944b10c1167161e7fb52c3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: globals.h,v 1.17 2003-03-15 01:34:36 didg Exp $
+ * $Id: globals.h,v 1.18 2003-04-16 22:45:10 samnoble Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -60,6 +60,7 @@ struct afp_options {
     char *uamlist;
     char *authprintdir;
     char *signature;
+    char *k5service, *k5realm;
     mode_t umask;
     mode_t save_mask;
 #ifdef ADMIN_GRP
index b5710bebd5ee9159d30851b509cf6b496f479f6e..b66c17dafb2313985c4dca9a1d3f3b45d1a97602 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: status.c,v 1.10 2003-03-11 09:35:40 didg Exp $
+ * $Id: status.c,v 1.11 2003-04-16 22:45:10 samnoble Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -36,7 +36,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;
 
@@ -59,6 +59,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));
 }
@@ -84,13 +86,17 @@ static int status_server(char *data, const char *server)
     data += len;
 
     /* make room for signature and net address offset. save location of
-     * signature offset. 
+     * 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
      * 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.  
+     *
+     * 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);
@@ -202,7 +208,7 @@ server_signature_done:
     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)
 {
@@ -212,7 +218,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:
@@ -276,8 +282,82 @@ 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 = 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;
+    } 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);
+
 }
 
 /* returns actual offset to signature */
@@ -310,7 +390,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;
@@ -350,7 +430,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);
@@ -363,16 +444,22 @@ 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);
+    /* 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 */
 
@@ -385,9 +472,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..15dc25494327afc94c5ba3a1e9600aa6fa7f6896 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.6 2003-04-16 22:45:10 samnoble 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..08ba1cdac08a767d8c4a9a6218a7739dcf2171c0 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.24 2003-04-16 22:45:11 samnoble Exp $
  *
  * Copyright (c) 1999 Adrian Sun (asun@zoology.washington.edu)
  * All Rights Reserved.  See COPYRIGHT.
@@ -466,7 +466,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;
index d7e5048fc4f7ea23909b7cfeda744c80352f0b76..29bb542f371fe98a0a695f4dff1b31b5287fea35 100644 (file)
@@ -40,6 +40,7 @@
 #define UAM_OPTION_COOKIE       (1 << 6) /* cookie handle */
 #define UAM_OPTION_PROTOCOL    (1 << 7) /* DSI or ASP */
 #define UAM_OPTION_CLIENTNAME   (1 << 8) /* get client IP address */
+#define UAM_OPTION_KRB5SERVICE  (1 << 9) /* service name for krb5 principal */
 
 /* some password options. you pass these in the length parameter and
  * get back the corresponding option. not all of these are implemented. */