Hello,

The "openssl s_server" command hard-codes a specific Kerberos keytab
filename, "/etc/krb5.keytab". This causes difficulties for two reasons:

1) Although it is common, this may not in fact be the default keytab
    as that is configurable in MIT Kerberos at both compile and run times
    (the [libdefaults] default_keytab_name parameter).

2) Users do not generally have access to the system keytab, meaning in
    practice only root can use s_server with Kerberos.

I have added a "s_server -keytab <filename>" option to set the keytab
location, and the default is now to not set the keytab at all. This uses
the *correct* default keytab (as supplied by the Kerberos library), and
also allows the user to transparently override it by setting KRB5_KTNAME.

I have also added an option "-krb5svc <service name>" to both s_client and
s_server to select a service other than "host", since an unprivileged user
will not normally be given the keys to the host principal, but rather an
application-specific one or a test principal created for this purpose
(e.g. test/host@REALM).

I'm attaching a patch against openssl-1.0.1c.

Thanks,

-- 
   Richard E. Silverman
diff --git a/apps/s_client.c b/apps/s_client.c
index fc806eb6..ddc9c857 100644
--- a/apps/s_client.c
+++ b/apps/s_client.c
@@ -209,6 +209,10 @@ static int c_showcerts=0;
 static char *keymatexportlabel=NULL;
 static int keymatexportlen=20;
 
+#ifndef OPENSSL_NO_KRB5
+static char *krb5svc=NULL;
+#endif
+
 static void sc_usage(void);
 static void print_stuff(BIO *berr,SSL *con,int full);
 #ifndef OPENSSL_NO_TLSEXT
@@ -346,6 +350,9 @@ static void sc_usage(void)
        BIO_printf(bio_err,"                 'prot' defines which one to 
assume.  Currently,\n");
        BIO_printf(bio_err,"                 only \"smtp\", \"pop3\", \"imap\", 
\"ftp\" and \"xmpp\"\n");
        BIO_printf(bio_err,"                 are supported.\n");
+#ifndef OPENSSL_NO_KRB5
+       BIO_printf(bio_err," -krb5svc arg  - Kerberos service name\n");
+#endif
 #ifndef OPENSSL_NO_ENGINE
        BIO_printf(bio_err," -engine id    - Initialise and use the specified 
engine\n");
 #endif
@@ -896,6 +903,13 @@ int MAIN(int argc, char **argv)
                else if (strcmp(*argv,"-nbio") == 0)
                        { c_nbio=1; }
 #endif
+#ifndef OPENSSL_NO_KRB5
+               else if (strcmp(*argv,"-krb5svc") == 0)
+                       {
+                       if (--argc < 1) goto bad;
+                       krb5svc= *(++argv);
+                       }
+#endif
                else if (strcmp(*argv,"-starttls") == 0)
                        {
                        if (--argc < 1) goto bad;
@@ -1241,6 +1255,8 @@ bad:
                 {
                SSL_set0_kssl_ctx(con, kctx);
                 kssl_ctx_setstring(kctx, KSSL_SERVER, host);
+                               if (krb5svc != NULL)
+                                       kssl_ctx_setstring(kctx, KSSL_SERVICE, 
krb5svc);
                }
 #endif /* OPENSSL_NO_KRB5  */
 /*     SSL_set_cipher_list(con,"RC4-MD5"); */
diff --git a/apps/s_server.c b/apps/s_server.c
index 3f9b3704..6316fe3a 100644
--- a/apps/s_server.c
+++ b/apps/s_server.c
@@ -265,6 +265,10 @@ static int accept_socket= -1;
 extern int verify_depth, verify_return_error;
 
 static char *cipher=NULL;
+#ifndef OPENSSL_NO_KRB5
+static char *krb5svc=NULL;
+static char *keytab=NULL;
+#endif
 static int s_server_verify=SSL_VERIFY_NONE;
 static int s_server_session_id_context = 1; /* anything will do */
 static const char *s_cert_file=TEST_CERT,*s_key_file=NULL;
@@ -502,6 +506,10 @@ static void sv_usage(void)
        BIO_printf(bio_err," -serverpref   - Use server's cipher 
preferences\n");
        BIO_printf(bio_err," -quiet        - No server output\n");
        BIO_printf(bio_err," -no_tmp_rsa   - Do not generate a tmp RSA key\n");
+#ifndef OPENSSL_NO_KRB5
+       BIO_printf(bio_err," -krb5svc arg  - Kerberos service name\n");
+       BIO_printf(bio_err," -keytab arg   - Kerberos keytab filename\n");
+#endif
 #ifndef OPENSSL_NO_PSK
        BIO_printf(bio_err," -psk_hint arg - PSK identity hint to use\n");
        BIO_printf(bio_err," -psk arg      - PSK in hex (without 0x)\n");
@@ -1113,6 +1121,18 @@ int MAIN(int argc, char *argv[])
                        if (--argc < 1) goto bad;
                        cipher= *(++argv);
                        }
+#ifndef OPENSSL_NO_KRB5
+               else if (strcmp(*argv,"-krb5svc") == 0)
+                       {
+                       if (--argc < 1) goto bad;
+                       krb5svc= *(++argv);
+                       }
+               else if (strcmp(*argv,"-keytab") == 0)
+                       {
+                       if (--argc < 1) goto bad;
+                       keytab= *(++argv);
+                       }
+#endif
                else if (strcmp(*argv,"-CAfile") == 0)
                        {
                        if (--argc < 1) goto bad;
@@ -1989,8 +2009,10 @@ static int sv_body(char *hostname, int s, unsigned char 
*context)
                if ((kctx = kssl_ctx_new()) != NULL)
                         {
                        SSL_set0_kssl_ctx(con, kctx);
-                        kssl_ctx_setstring(kctx, KSSL_SERVICE, KRB5SVC);
-                        kssl_ctx_setstring(kctx, KSSL_KEYTAB, KRB5KEYTAB);
+                        kssl_ctx_setstring(kctx, KSSL_SERVICE,
+                                                                               
   krb5svc == NULL ? KRB5SVC : krb5svc);
+                                               if (keytab != NULL)
+                                                       
kssl_ctx_setstring(kctx, KSSL_KEYTAB, keytab);
                         }
 #endif /* OPENSSL_NO_KRB5 */
                if(context)
@@ -2580,8 +2602,10 @@ static int www_body(char *hostname, int s, unsigned char 
*context)
 #ifndef OPENSSL_NO_KRB5
        if ((kctx = kssl_ctx_new()) != NULL)
                {
-               kssl_ctx_setstring(kctx, KSSL_SERVICE, KRB5SVC);
-               kssl_ctx_setstring(kctx, KSSL_KEYTAB, KRB5KEYTAB);
+               kssl_ctx_setstring(kctx, KSSL_SERVICE,
+                                                  krb5svc == NULL ? KRB5SVC : 
krb5svc);
+               if (keytab != NULL)
+                       kssl_ctx_setstring(kctx, KSSL_KEYTAB, keytab);
                }
 #endif /* OPENSSL_NO_KRB5 */
        if(context) SSL_set_session_id_context(con, context,
diff --git a/doc/apps/s_client.pod b/doc/apps/s_client.pod
index 4ebf7b58..389f5e4e 100644
--- a/doc/apps/s_client.pod
+++ b/doc/apps/s_client.pod
@@ -34,6 +34,7 @@ B<openssl> B<s_client>
 [B<-no_ssl2>]
 [B<-no_ssl3>]
 [B<-no_tls1>]
+[B<-krb5svc service>]
 [B<-bugs>]
 [B<-cipher cipherlist>]
 [B<-starttls protocol>]
@@ -187,6 +188,12 @@ cannot handle this technique and will fail to connect. 
Some servers only
 work if TLS is turned off with the B<-no_tls> option others will only
 support SSL v2 and may need the B<-ssl2> option.
 
+=item B<-krb5svc service>
+
+the Kerberos service name to use (default "host"). s_client will obtain a
+Kerberos ticket for the principal I<service>/server@REALM, and the server
+must be configured to expect that (e.g. with openssl s_client -krb5svc).
+
 =item B<-bugs>
 
 there are several known bug in SSL and TLS implementations. Adding this
diff --git a/doc/apps/s_server.pod b/doc/apps/s_server.pod
index 3e503e17..087a0fb9 100644
--- a/doc/apps/s_server.pod
+++ b/doc/apps/s_server.pod
@@ -33,6 +33,8 @@ B<openssl> B<s_server>
 [B<-state>]
 [B<-CApath directory>]
 [B<-CAfile filename>]
+[B<-krb5svc service>]
+[B<-keytab filename>]
 [B<-nocert>]
 [B<-cipher cipherlist>]
 [B<-quiet>]
@@ -119,6 +121,17 @@ if this option is set then no certificate is used. This 
restricts the
 cipher suites available to the anonymous ones (currently just anonymous
 DH).
 
+=item B<-krb5svc service>
+
+the Kerberos service name to use (default "host"). This means s_server
+will expect a ticket for the principal I<service>/hostname@REALM, and will
+need keys for that principal in its keytab.
+
+=item B<-keytab filename>
+
+the Kerberos "keytab" (key table) file, containing keys for the s_server
+service principal (Kerberos identity; see -krb5svc).
+
 =item B<-dhparam filename>
 
 the DH parameter file to use. The ephemeral DH cipher suites generate keys
diff --git a/ssl/kssl.c b/ssl/kssl.c
index fd7c67bb..e539542a 100644
--- a/ssl/kssl.c
+++ b/ssl/kssl.c
@@ -1647,7 +1647,7 @@ kssl_ctx_setprinc(KSSL_CTX *kssl_ctx, int which,
 /*     Set one of the plain (char *) string members of the kssl_ctx struct.
 **     Default values should be:
 **             which == KSSL_SERVICE   =>      "khost" (KRB5SVC)
-**             which == KSSL_KEYTAB    =>      "/etc/krb5.keytab" (KRB5KEYTAB)
+**             which == KSSL_KEYTAB    =>      NULL (use system default)
 */
 krb5_error_code
 kssl_ctx_setstring(KSSL_CTX *kssl_ctx, int which, char *text)
diff --git a/ssl/kssl.h b/ssl/kssl.h
index 8242fd5e..b7f762e6 100644
--- a/ssl/kssl.h
+++ b/ssl/kssl.h
@@ -100,10 +100,6 @@ typedef unsigned char krb5_octet;
 #define KRB5SVC        "host"
 #endif
 
-#ifndef        KRB5KEYTAB
-#define KRB5KEYTAB     "/etc/krb5.keytab"
-#endif
-
 #ifndef KRB5SENDAUTH
 #define KRB5SENDAUTH   1
 #endif

Reply via email to