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