Use rxgk in afsconf_BuildServerSecurityObjects
[openafs.git] / src / auth / authcon.c
index c5ff5d1..bff0f79 100644 (file)
@@ -9,6 +9,7 @@
 
 #include <afsconfig.h>
 #include <afs/param.h>
+#include <afs/stds.h>
 
 #include <roken.h>
 
 # pragma GCC diagnostic warning "-Wdeprecated-declarations"
 #endif
 
-#include <afs/stds.h>
-#include <afs/pthread_glock.h>
-#include <sys/types.h>
-#ifdef AFS_NT40_ENV
-#include <winsock2.h>
-#else
-#include <sys/file.h>
-#include <sys/time.h>
-#include <netinet/in.h>
-#include <netdb.h>
-#endif
-#include <string.h>
-#include <stdio.h>
-
 #define HC_DEPRECATED
 #include <hcrypto/des.h>
+#include <hcrypto/rand.h>
 
 #include <rx/rxkad.h>
 #include <rx/rx.h>
 
+#include <afs/pthread_glock.h>
+
 #include "cellconfig.h"
 #include "keys.h"
 #include "ktc.h"
 #include "auth.h"
 
+#ifdef AFS_RXGK_ENV
+# include <rx/rxgk.h>
+#endif
+
 /* return a null security object if nothing else can be done */
 static afs_int32
 QuickAuth(struct rx_securityClass **astr, afs_int32 *aindex)
@@ -52,7 +46,31 @@ QuickAuth(struct rx_securityClass **astr, afs_int32 *aindex)
     return 0;
 }
 
-#if !defined(UKERNEL)
+static int _afsconf_GetRxkadKrb5Key(void *arock, int kvno, int enctype, void *outkey,
+                                   size_t *keylen)
+{
+    struct afsconf_dir *adir = arock;
+    struct afsconf_typedKey *kobj;
+    struct rx_opaque *keymat;
+    afsconf_keyType tktype;
+    int tkvno, tenctype;
+    int code;
+
+    code = afsconf_GetKeyByTypes(adir, afsconf_rxkad_krb5, kvno, enctype, &kobj);
+    if (code != 0)
+       return code;
+    afsconf_typedKey_values(kobj, &tktype, &tkvno, &tenctype, &keymat);
+    if (*keylen < keymat->len) {
+       afsconf_typedKey_put(&kobj);
+       return AFSCONF_BADKEY;
+    }
+    memcpy(outkey, keymat->val, keymat->len);
+    *keylen = keymat->len;
+    afsconf_typedKey_put(&kobj);
+    return 0;
+}
+
+
 /* Return an appropriate security class and index */
 afs_int32
 afsconf_ServerAuth(void *arock,
@@ -64,7 +82,8 @@ afsconf_ServerAuth(void *arock,
 
     LOCK_GLOBAL_MUTEX;
     tclass = (struct rx_securityClass *)
-       rxkad_NewServerSecurityObject(0, adir, afsconf_GetKey, NULL);
+       rxkad_NewKrb5ServerSecurityObject(0, adir, afsconf_GetKey,
+                                         _afsconf_GetRxkadKrb5Key, NULL);
     if (tclass) {
        *astr = tclass;
        *aindex = RX_SECIDX_KAD;
@@ -75,7 +94,6 @@ afsconf_ServerAuth(void *arock,
        return 2;
     }
 }
-#endif /* !defined(UKERNEL) */
 
 static afs_int32
 GenericAuth(struct afsconf_dir *adir,
@@ -83,43 +101,74 @@ GenericAuth(struct afsconf_dir *adir,
            afs_int32 *aindex,
            rxkad_level enclevel)
 {
-    char tbuffer[256];
+    int enctype_preflist[]={18, 17, 23, 16, 0};
+    char tbuffer[512];
     struct ktc_encryptionKey key, session;
     struct rx_securityClass *tclass;
     afs_int32 kvno;
     afs_int32 ticketLen;
     afs_int32 code;
+    int use_krb5=0;
+    struct afsconf_typedKey *kobj;
+    struct rx_opaque *keymat;
+    int *et;
 
     /* first, find the right key and kvno to use */
-    code = afsconf_GetLatestKey(adir, &kvno, &key);
-    if (code) {
-       return QuickAuth(astr, aindex);
+
+    et = enctype_preflist;
+    while(*et != 0) {
+       code = afsconf_GetLatestKeyByTypes(adir, afsconf_rxkad_krb5, *et,
+                                          &kobj);
+       if (code == 0) {
+           afsconf_keyType tktype;
+           int tenctype;
+           afsconf_typedKey_values(kobj, &tktype, &kvno, &tenctype, &keymat);
+           RAND_add(keymat->val, keymat->len, 0.0);
+           use_krb5 = 1;
+           break;
+       }
+       et++;
     }
 
-    /* next create random session key, using key for seed to good random */
-    DES_init_random_number_generator((DES_cblock *) &key);
+    if (use_krb5 == 0) {
+       code = afsconf_GetLatestKey(adir, &kvno, &key);
+       if (code) {
+           return QuickAuth(astr, aindex);
+       }
+       /* next create random session key, using key for seed to good random */
+       DES_init_random_number_generator((DES_cblock *) &key);
+    }
     code = DES_new_random_key((DES_cblock *) &session);
     if (code) {
+       if (use_krb5)
+           afsconf_typedKey_put(&kobj);
        return QuickAuth(astr, aindex);
     }
 
-    /* now create the actual ticket */
-    ticketLen = sizeof(tbuffer);
-    memset(tbuffer, '\0', sizeof(tbuffer));
-    code =
-       tkt_MakeTicket(tbuffer, &ticketLen, &key, AUTH_SUPERUSER, "", "", 0,
-                      0xffffffff, &session, 0, "afs", "");
-    /* parms were buffer, ticketlen, key to seal ticket with, principal
-     * name, instance and cell, start time, end time, session key to seal
-     * in ticket, inet host, server name and server instance */
+    if (use_krb5) {
+       ticketLen = sizeof(tbuffer);
+       memset(tbuffer, '\0', sizeof(tbuffer));
+       code =
+           tkt_MakeTicket5(tbuffer, &ticketLen, *et, &kvno, keymat->val,
+                           keymat->len, AUTH_SUPERUSER, "", "", 0, 0x7fffffff,
+                           &session, "afs", "");
+       afsconf_typedKey_put(&kobj);
+    } else {
+       /* now create the actual ticket */
+       ticketLen = sizeof(tbuffer);
+       memset(tbuffer, '\0', sizeof(tbuffer));
+       code =
+           tkt_MakeTicket(tbuffer, &ticketLen, &key, AUTH_SUPERUSER, "", "", 0,
+                          0xffffffff, &session, 0, "afs", "");
+       /* parms were buffer, ticketlen, key to seal ticket with, principal
+        * name, instance and cell, start time, end time, session key to seal
+        * in ticket, inet host, server name and server instance */
+    }
     if (code) {
        return QuickAuth(astr, aindex);
     }
 
-    /* Next, we have ticket, kvno and session key, authenticate the connection.
-     * We use a magic # instead of a constant because of basic compilation
-     * order when compiling the system from scratch (rx/rxkad.h isn't installed
-     * yet). */
+    /* Next, we have ticket, kvno and session key, authenticate the connection.*/
     tclass = (struct rx_securityClass *)
        rxkad_NewClientSecurityObject(enclevel, &session, kvno, ticketLen,
                                      tbuffer);
@@ -248,7 +297,6 @@ afsconf_SetSecurityFlags(struct afsconf_dir *dir,
  * Build a set of security classes suitable for a server accepting
  * incoming connections
  */
-#if !defined(UKERNEL)
 void
 afsconf_BuildServerSecurityObjects(void *rock,
                                   struct rx_securityClass ***classes,
@@ -256,23 +304,24 @@ afsconf_BuildServerSecurityObjects(void *rock,
 {
     struct afsconf_dir *dir = rock;
 
-    if (dir->securityFlags & AFSCONF_SECOPTS_ALWAYSENCRYPT)
-       *numClasses = 4;
-    else
-       *numClasses = 3;
+    *numClasses = RX_SECIDX_GK+1;
 
     *classes = calloc(*numClasses, sizeof(**classes));
 
-    (*classes)[0] = rxnull_NewServerSecurityObject();
-    (*classes)[1] = NULL;
-    (*classes)[2] = rxkad_NewServerSecurityObject(0, dir,
-                                                 afsconf_GetKey, NULL);
+    (*classes)[RX_SECIDX_NULL] = rxnull_NewServerSecurityObject();
+    (*classes)[RX_SECIDX_KAD] =
+       rxkad_NewKrb5ServerSecurityObject(0, dir, afsconf_GetKey,
+                                         _afsconf_GetRxkadKrb5Key, NULL);
 
     if (dir->securityFlags & AFSCONF_SECOPTS_ALWAYSENCRYPT)
-       (*classes)[3] = rxkad_NewServerSecurityObject(rxkad_crypt, dir,
-                                                     afsconf_GetKey, NULL);
-}
+       (*classes)[RX_SECIDX_KAE] =
+           rxkad_NewKrb5ServerSecurityObject(rxkad_crypt, dir, afsconf_GetKey,
+                                             _afsconf_GetRxkadKrb5Key, NULL);
+#ifdef AFS_RXGK_ENV
+    (*classes)[RX_SECIDX_GK] =
+        rxgk_NewServerSecurityObject(rock, afsconf_GetRXGKKey);
 #endif
+}
 
 /*!
  * Pick a security class to use for an outgoing connection
@@ -342,7 +391,8 @@ afsconf_PickClientSecObj(struct afsconf_dir *dir, afsconf_secflags flags,
             * explicitly requested. Check for this, and bail out if we
             * get one. Note that this leaks a security object at present
             */
-           if (scIndex == RX_SECIDX_NULL) {
+           if (!(flags & AFSCONF_SECOPTS_FALLBACK_NULL) &&
+               *scIndex == RX_SECIDX_NULL) {
                sc = NULL;
                code = AFSCONF_NOTFOUND;
                goto out;