summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog10
-rw-r--r--auth.h3
-rw-r--r--auth2-gss.c243
-rw-r--r--auth2.c18
-rw-r--r--compat.c8
-rw-r--r--compat.h3
-rw-r--r--gss-genr.c256
-rw-r--r--gss-serv-krb5.c168
-rw-r--r--gss-serv.c291
-rw-r--r--monitor.c92
-rw-r--r--monitor.h5
-rw-r--r--monitor_wrap.c73
-rw-r--r--monitor_wrap.h10
-rw-r--r--readconf.c26
-rw-r--r--readconf.h4
-rw-r--r--servconf.c24
-rw-r--r--servconf.h4
-rw-r--r--session.c31
-rw-r--r--session.h5
-rw-r--r--ssh-gss.h109
-rw-r--r--ssh_config.514
-rw-r--r--sshconnect2.c252
-rw-r--r--sshd_config6
-rw-r--r--sshd_config.515
24 files changed, 1646 insertions, 24 deletions
diff --git a/ChangeLog b/ChangeLog
index e8727e2f0..142af1b06 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,6 +2,14 @@
2 - (djm) Bug #629: Mark ssh_config option "pamauthenticationviakbdint" 2 - (djm) Bug #629: Mark ssh_config option "pamauthenticationviakbdint"
3 as deprecated. Remove mention from README.privsep. Patch from 3 as deprecated. Remove mention from README.privsep. Patch from
4 aet AT cc.hut.fi 4 aet AT cc.hut.fi
5 - (dtucker) OpenBSD CVS Sync
6 - markus@cvs.openbsd.org 2003/08/22 10:56:09
7 [auth2.c auth2-gss.c auth.h compat.c compat.h gss-genr.c gss-serv-krb5.c
8 gss-serv.c monitor.c monitor.h monitor_wrap.c monitor_wrap.h readconf.c
9 readconf.h servconf.c servconf.h session.c session.h ssh-gss.h
10 ssh_config.5 sshconnect2.c sshd_config sshd_config.5]
11 support GSS API user authentication; patches from Simon Wilkinson,
12 stripped down and tested by Jakob and myself.
5 13
620030825 1420030825
7 - (djm) Bug #621: Select OpenSC keys by usage attributes. Patch from 15 - (djm) Bug #621: Select OpenSC keys by usage attributes. Patch from
@@ -874,4 +882,4 @@
874 - Fix sshd BindAddress and -b options for systems using fake-getaddrinfo. 882 - Fix sshd BindAddress and -b options for systems using fake-getaddrinfo.
875 Report from murple@murple.net, diagnosis from dtucker@zip.com.au 883 Report from murple@murple.net, diagnosis from dtucker@zip.com.au
876 884
877$Id: ChangeLog,v 1.2906 2003/08/26 00:48:14 djm Exp $ 885$Id: ChangeLog,v 1.2907 2003/08/26 01:49:55 dtucker Exp $
diff --git a/auth.h b/auth.h
index 1ed92e018..6beff7cc3 100644
--- a/auth.h
+++ b/auth.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: auth.h,v 1.43 2003/07/22 13:35:22 markus Exp $ */ 1/* $OpenBSD: auth.h,v 1.44 2003/08/22 10:56:08 markus Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2000 Markus Friedl. All rights reserved. 4 * Copyright (c) 2000 Markus Friedl. All rights reserved.
@@ -67,6 +67,7 @@ struct Authctxt {
67 krb5_principal krb5_user; 67 krb5_principal krb5_user;
68 char *krb5_ticket_file; 68 char *krb5_ticket_file;
69#endif 69#endif
70 void *methoddata;
70}; 71};
71/* 72/*
72 * Every authentication method has to handle authentication requests for 73 * Every authentication method has to handle authentication requests for
diff --git a/auth2-gss.c b/auth2-gss.c
new file mode 100644
index 000000000..c7651112d
--- /dev/null
+++ b/auth2-gss.c
@@ -0,0 +1,243 @@
1/* $OpenBSD: auth2-gss.c,v 1.1 2003/08/22 10:56:08 markus Exp $ */
2
3/*
4 * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#include "includes.h"
28
29#ifdef GSSAPI
30
31#include "auth.h"
32#include "ssh2.h"
33#include "xmalloc.h"
34#include "log.h"
35#include "dispatch.h"
36#include "servconf.h"
37#include "compat.h"
38#include "packet.h"
39#include "monitor_wrap.h"
40
41#include "ssh-gss.h"
42
43extern ServerOptions options;
44
45static void input_gssapi_token(int type, u_int32_t plen, void *ctxt);
46static void input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt);
47static void input_gssapi_errtok(int, u_int32_t, void *);
48
49/*
50 * We only support those mechanisms that we know about (ie ones that we know
51 * how to check local user kuserok and the like
52 */
53static int
54userauth_gssapi(Authctxt *authctxt)
55{
56 gss_OID_desc oid = {0, NULL};
57 Gssctxt *ctxt = NULL;
58 int mechs;
59 gss_OID_set supported;
60 int present;
61 OM_uint32 ms;
62 u_int len;
63 char *doid = NULL;
64
65 if (!authctxt->valid || authctxt->user == NULL)
66 return (0);
67
68 mechs = packet_get_int();
69 if (mechs == 0) {
70 debug("Mechanism negotiation is not supported");
71 return (0);
72 }
73
74 ssh_gssapi_supported_oids(&supported);
75 do {
76 mechs--;
77
78 if (doid)
79 xfree(doid);
80
81 doid = packet_get_string(&len);
82
83 if (doid[0] != SSH_GSS_OIDTYPE || doid[1] != len-2) {
84 logit("Mechanism OID received using the old encoding form");
85 oid.elements = doid;
86 oid.length = len;
87 } else {
88 oid.elements = doid + 2;
89 oid.length = len - 2;
90 }
91 gss_test_oid_set_member(&ms, &oid, supported, &present);
92 } while (mechs > 0 && !present);
93
94 gss_release_oid_set(&ms, &supported);
95
96 if (!present) {
97 xfree(doid);
98 return (0);
99 }
100
101 if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, &oid))))
102 return (0);
103
104 authctxt->methoddata=(void *)ctxt;
105
106 packet_start(SSH2_MSG_USERAUTH_GSSAPI_RESPONSE);
107
108 /* Return OID in same format as we received it*/
109 packet_put_string(doid, len);
110
111 packet_send();
112 xfree(doid);
113
114 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, &input_gssapi_token);
115 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, &input_gssapi_errtok);
116 authctxt->postponed = 1;
117
118 return (0);
119}
120
121static void
122input_gssapi_token(int type, u_int32_t plen, void *ctxt)
123{
124 Authctxt *authctxt = ctxt;
125 Gssctxt *gssctxt;
126 gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER;
127 gss_buffer_desc recv_tok;
128 OM_uint32 maj_status, min_status;
129 u_int len;
130
131 if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep))
132 fatal("No authentication or GSSAPI context");
133
134 gssctxt = authctxt->methoddata;
135 recv_tok.value = packet_get_string(&len);
136 recv_tok.length = len; /* u_int vs. size_t */
137
138 packet_check_eom();
139
140 maj_status = PRIVSEP(ssh_gssapi_accept_ctx(gssctxt, &recv_tok,
141 &send_tok, NULL));
142
143 xfree(recv_tok.value);
144
145 if (GSS_ERROR(maj_status)) {
146 if (send_tok.length != 0) {
147 packet_start(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK);
148 packet_put_string(send_tok.value, send_tok.length);
149 packet_send();
150 }
151 authctxt->postponed = 0;
152 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
153 userauth_finish(authctxt, 0, "gssapi");
154 } else {
155 if (send_tok.length != 0) {
156 packet_start(SSH2_MSG_USERAUTH_GSSAPI_TOKEN);
157 packet_put_string(send_tok.value, send_tok.length);
158 packet_send();
159 }
160 if (maj_status == GSS_S_COMPLETE) {
161 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
162 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE,
163 &input_gssapi_exchange_complete);
164 }
165 }
166
167 gss_release_buffer(&min_status, &send_tok);
168}
169
170static void
171input_gssapi_errtok(int type, u_int32_t plen, void *ctxt)
172{
173 Authctxt *authctxt = ctxt;
174 Gssctxt *gssctxt;
175 gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER;
176 gss_buffer_desc recv_tok;
177 OM_uint32 maj_status;
178
179 if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep))
180 fatal("No authentication or GSSAPI context");
181
182 gssctxt = authctxt->methoddata;
183 recv_tok.value = packet_get_string(&recv_tok.length);
184
185 packet_check_eom();
186
187 /* Push the error token into GSSAPI to see what it says */
188 maj_status = PRIVSEP(ssh_gssapi_accept_ctx(gssctxt, &recv_tok,
189 &send_tok, NULL));
190
191 xfree(recv_tok.value);
192
193 /* We can't return anything to the client, even if we wanted to */
194 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
195 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL);
196
197 /* The client will have already moved on to the next auth */
198
199 gss_release_buffer(&maj_status, &send_tok);
200}
201
202/*
203 * This is called when the client thinks we've completed authentication.
204 * It should only be enabled in the dispatch handler by the function above,
205 * which only enables it once the GSSAPI exchange is complete.
206 */
207
208static void
209input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt)
210{
211 Authctxt *authctxt = ctxt;
212 Gssctxt *gssctxt;
213 int authenticated;
214
215 if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep))
216 fatal("No authentication or GSSAPI context");
217
218 gssctxt = authctxt->methoddata;
219
220 /*
221 * We don't need to check the status, because the stored credentials
222 * which userok uses are only populated once the context init step
223 * has returned complete.
224 */
225
226 packet_check_eom();
227
228 authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user));
229
230 authctxt->postponed = 0;
231 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
232 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL);
233 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
234 userauth_finish(authctxt, authenticated, "gssapi");
235}
236
237Authmethod method_gssapi = {
238 "gssapi",
239 userauth_gssapi,
240 &options.gss_authentication
241};
242
243#endif /* GSSAPI */
diff --git a/auth2.c b/auth2.c
index e6ec8ddcd..4a305a416 100644
--- a/auth2.c
+++ b/auth2.c
@@ -23,7 +23,7 @@
23 */ 23 */
24 24
25#include "includes.h" 25#include "includes.h"
26RCSID("$OpenBSD: auth2.c,v 1.99 2003/06/24 08:23:46 markus Exp $"); 26RCSID("$OpenBSD: auth2.c,v 1.100 2003/08/22 10:56:08 markus Exp $");
27 27
28#include "ssh2.h" 28#include "ssh2.h"
29#include "xmalloc.h" 29#include "xmalloc.h"
@@ -36,6 +36,10 @@ RCSID("$OpenBSD: auth2.c,v 1.99 2003/06/24 08:23:46 markus Exp $");
36#include "pathnames.h" 36#include "pathnames.h"
37#include "monitor_wrap.h" 37#include "monitor_wrap.h"
38 38
39#ifdef GSSAPI
40#include "ssh-gss.h"
41#endif
42
39/* import */ 43/* import */
40extern ServerOptions options; 44extern ServerOptions options;
41extern u_char *session_id2; 45extern u_char *session_id2;
@@ -53,10 +57,16 @@ extern Authmethod method_hostbased;
53#ifdef KRB5 57#ifdef KRB5
54extern Authmethod method_kerberos; 58extern Authmethod method_kerberos;
55#endif 59#endif
60#ifdef GSSAPI
61extern Authmethod method_gssapi;
62#endif
56 63
57Authmethod *authmethods[] = { 64Authmethod *authmethods[] = {
58 &method_none, 65 &method_none,
59 &method_pubkey, 66 &method_pubkey,
67#ifdef GSSAPI
68 &method_gssapi,
69#endif
60 &method_passwd, 70 &method_passwd,
61 &method_kbdint, 71 &method_kbdint,
62 &method_hostbased, 72 &method_hostbased,
@@ -184,6 +194,12 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt)
184 } 194 }
185 /* reset state */ 195 /* reset state */
186 auth2_challenge_stop(authctxt); 196 auth2_challenge_stop(authctxt);
197
198#ifdef GSSAPI
199 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
200 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
201#endif
202
187 authctxt->postponed = 0; 203 authctxt->postponed = 0;
188 204
189 /* try to authenticate user */ 205 /* try to authenticate user */
diff --git a/compat.c b/compat.c
index 63a5d91ff..6bd42a6f5 100644
--- a/compat.c
+++ b/compat.c
@@ -23,7 +23,7 @@
23 */ 23 */
24 24
25#include "includes.h" 25#include "includes.h"
26RCSID("$OpenBSD: compat.c,v 1.67 2003/04/08 20:21:28 itojun Exp $"); 26RCSID("$OpenBSD: compat.c,v 1.68 2003/08/22 10:56:09 markus Exp $");
27 27
28#include "buffer.h" 28#include "buffer.h"
29#include "packet.h" 29#include "packet.h"
@@ -79,7 +79,11 @@ compat_datafellows(const char *version)
79 { "OpenSSH_2.5.3*", SSH_BUG_NOREKEY|SSH_BUG_EXTEOF}, 79 { "OpenSSH_2.5.3*", SSH_BUG_NOREKEY|SSH_BUG_EXTEOF},
80 { "OpenSSH_2.*," 80 { "OpenSSH_2.*,"
81 "OpenSSH_3.0*," 81 "OpenSSH_3.0*,"
82 "OpenSSH_3.1*", SSH_BUG_EXTEOF}, 82 "OpenSSH_3.1*", SSH_BUG_EXTEOF|SSH_BUG_GSSAPI_BER},
83 { "OpenSSH_3.2*,"
84 "OpenSSH_3.3*,"
85 "OpenSSH_3.4*,"
86 "OpenSSH_3.5*", SSH_BUG_GSSAPI_BER},
83 { "Sun_SSH_1.0*", SSH_BUG_NOREKEY|SSH_BUG_EXTEOF}, 87 { "Sun_SSH_1.0*", SSH_BUG_NOREKEY|SSH_BUG_EXTEOF},
84 { "OpenSSH*", 0 }, 88 { "OpenSSH*", 0 },
85 { "*MindTerm*", 0 }, 89 { "*MindTerm*", 0 },
diff --git a/compat.h b/compat.h
index 881e450d3..a21e473c5 100644
--- a/compat.h
+++ b/compat.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: compat.h,v 1.34 2003/04/01 10:31:26 markus Exp $ */ 1/* $OpenBSD: compat.h,v 1.35 2003/08/22 10:56:09 markus Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1999, 2000, 2001 Markus Friedl. All rights reserved. 4 * Copyright (c) 1999, 2000, 2001 Markus Friedl. All rights reserved.
@@ -56,6 +56,7 @@
56#define SSH_BUG_K5USER 0x00400000 56#define SSH_BUG_K5USER 0x00400000
57#define SSH_BUG_PROBE 0x00800000 57#define SSH_BUG_PROBE 0x00800000
58#define SSH_BUG_FIRSTKEX 0x01000000 58#define SSH_BUG_FIRSTKEX 0x01000000
59#define SSH_BUG_GSSAPI_BER 0x02000000
59 60
60void enable_compat13(void); 61void enable_compat13(void);
61void enable_compat20(void); 62void enable_compat20(void);
diff --git a/gss-genr.c b/gss-genr.c
new file mode 100644
index 000000000..bda12d6f1
--- /dev/null
+++ b/gss-genr.c
@@ -0,0 +1,256 @@
1/* $OpenBSD: gss-genr.c,v 1.1 2003/08/22 10:56:09 markus Exp $ */
2
3/*
4 * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#include "includes.h"
28
29#ifdef GSSAPI
30
31#include "xmalloc.h"
32#include "bufaux.h"
33#include "compat.h"
34#include "log.h"
35#include "monitor_wrap.h"
36
37#include "ssh-gss.h"
38
39
40/* Check that the OID in a data stream matches that in the context */
41int
42ssh_gssapi_check_oid(Gssctxt *ctx, void *data, size_t len)
43{
44 return (ctx != NULL && ctx->oid != GSS_C_NO_OID &&
45 ctx->oid->length == len &&
46 memcmp(ctx->oid->elements, data, len) == 0);
47}
48
49/* Set the contexts OID from a data stream */
50void
51ssh_gssapi_set_oid_data(Gssctxt *ctx, void *data, size_t len)
52{
53 if (ctx->oid != GSS_C_NO_OID) {
54 xfree(ctx->oid->elements);
55 xfree(ctx->oid);
56 }
57 ctx->oid = xmalloc(sizeof(gss_OID_desc));
58 ctx->oid->length = len;
59 ctx->oid->elements = xmalloc(len);
60 memcpy(ctx->oid->elements, data, len);
61}
62
63/* Set the contexts OID */
64void
65ssh_gssapi_set_oid(Gssctxt *ctx, gss_OID oid)
66{
67 ssh_gssapi_set_oid_data(ctx, oid->elements, oid->length);
68}
69
70/* All this effort to report an error ... */
71void
72ssh_gssapi_error(Gssctxt *ctxt)
73{
74 debug("%s", ssh_gssapi_last_error(ctxt, NULL, NULL));
75}
76
77char *
78ssh_gssapi_last_error(Gssctxt *ctxt,
79 OM_uint32 *major_status, OM_uint32 *minor_status)
80{
81 OM_uint32 lmin;
82 gss_buffer_desc msg = GSS_C_EMPTY_BUFFER;
83 OM_uint32 ctx;
84 Buffer b;
85 char *ret;
86
87 buffer_init(&b);
88
89 if (major_status != NULL)
90 *major_status = ctxt->major;
91 if (minor_status != NULL)
92 *minor_status = ctxt->minor;
93
94 ctx = 0;
95 /* The GSSAPI error */
96 do {
97 gss_display_status(&lmin, ctxt->major,
98 GSS_C_GSS_CODE, GSS_C_NULL_OID, &ctx, &msg);
99
100 buffer_append(&b, msg.value, msg.length);
101 buffer_put_char(&b, '\n');
102
103 gss_release_buffer(&lmin, &msg);
104 } while (ctx != 0);
105
106 /* The mechanism specific error */
107 do {
108 gss_display_status(&lmin, ctxt->minor,
109 GSS_C_MECH_CODE, GSS_C_NULL_OID, &ctx, &msg);
110
111 buffer_append(&b, msg.value, msg.length);
112 buffer_put_char(&b, '\n');
113
114 gss_release_buffer(&lmin, &msg);
115 } while (ctx != 0);
116
117 buffer_put_char(&b, '\0');
118 ret = xmalloc(buffer_len(&b));
119 buffer_get(&b, ret, buffer_len(&b));
120 buffer_free(&b);
121 return (ret);
122}
123
124/*
125 * Initialise our GSSAPI context. We use this opaque structure to contain all
126 * of the data which both the client and server need to persist across
127 * {accept,init}_sec_context calls, so that when we do it from the userauth
128 * stuff life is a little easier
129 */
130void
131ssh_gssapi_build_ctx(Gssctxt **ctx)
132{
133 *ctx = xmalloc(sizeof (Gssctxt));
134 (*ctx)->major = 0;
135 (*ctx)->minor = 0;
136 (*ctx)->context = GSS_C_NO_CONTEXT;
137 (*ctx)->name = GSS_C_NO_NAME;
138 (*ctx)->oid = GSS_C_NO_OID;
139 (*ctx)->creds = GSS_C_NO_CREDENTIAL;
140 (*ctx)->client = GSS_C_NO_NAME;
141 (*ctx)->client_creds = GSS_C_NO_CREDENTIAL;
142}
143
144/* Delete our context, providing it has been built correctly */
145void
146ssh_gssapi_delete_ctx(Gssctxt **ctx)
147{
148 OM_uint32 ms;
149
150 if ((*ctx) == NULL)
151 return;
152 if ((*ctx)->context != GSS_C_NO_CONTEXT)
153 gss_delete_sec_context(&ms, &(*ctx)->context, GSS_C_NO_BUFFER);
154 if ((*ctx)->name != GSS_C_NO_NAME)
155 gss_release_name(&ms, &(*ctx)->name);
156 if ((*ctx)->oid != GSS_C_NO_OID) {
157 xfree((*ctx)->oid->elements);
158 xfree((*ctx)->oid);
159 (*ctx)->oid = GSS_C_NO_OID;
160 }
161 if ((*ctx)->creds != GSS_C_NO_CREDENTIAL)
162 gss_release_cred(&ms, &(*ctx)->creds);
163 if ((*ctx)->client != GSS_C_NO_NAME)
164 gss_release_name(&ms, &(*ctx)->client);
165 if ((*ctx)->client_creds != GSS_C_NO_CREDENTIAL)
166 gss_release_cred(&ms, &(*ctx)->client_creds);
167
168 xfree(*ctx);
169 *ctx = NULL;
170}
171
172/*
173 * Wrapper to init_sec_context
174 * Requires that the context contains:
175 * oid
176 * server name (from ssh_gssapi_import_name)
177 */
178OM_uint32
179ssh_gssapi_init_ctx(Gssctxt *ctx, int deleg_creds, gss_buffer_desc *recv_tok,
180 gss_buffer_desc* send_tok, OM_uint32 *flags)
181{
182 int deleg_flag = 0;
183
184 if (deleg_creds) {
185 deleg_flag = GSS_C_DELEG_FLAG;
186 debug("Delegating credentials");
187 }
188
189 ctx->major = gss_init_sec_context(&ctx->minor,
190 GSS_C_NO_CREDENTIAL, &ctx->context, ctx->name, ctx->oid,
191 GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG | deleg_flag,
192 0, NULL, recv_tok, NULL, send_tok, flags, NULL);
193
194 if (GSS_ERROR(ctx->major))
195 ssh_gssapi_error(ctx);
196
197 return (ctx->major);
198}
199
200/* Create a service name for the given host */
201OM_uint32
202ssh_gssapi_import_name(Gssctxt *ctx, const char *host)
203{
204 gss_buffer_desc gssbuf;
205
206 gssbuf.length = sizeof("host@") + strlen(host);
207 gssbuf.value = xmalloc(gssbuf.length);
208 snprintf(gssbuf.value, gssbuf.length, "host@%s", host);
209
210 if ((ctx->major = gss_import_name(&ctx->minor,
211 &gssbuf, GSS_C_NT_HOSTBASED_SERVICE, &ctx->name)))
212 ssh_gssapi_error(ctx);
213
214 xfree(gssbuf.value);
215 return (ctx->major);
216}
217
218/* Acquire credentials for a server running on the current host.
219 * Requires that the context structure contains a valid OID
220 */
221
222/* Returns a GSSAPI error code */
223OM_uint32
224ssh_gssapi_acquire_cred(Gssctxt *ctx)
225{
226 OM_uint32 status;
227 char lname[MAXHOSTNAMELEN];
228 gss_OID_set oidset;
229
230 gss_create_empty_oid_set(&status, &oidset);
231 gss_add_oid_set_member(&status, ctx->oid, &oidset);
232
233 if (gethostname(lname, MAXHOSTNAMELEN))
234 return (-1);
235
236 if (GSS_ERROR(ssh_gssapi_import_name(ctx, lname)))
237 return (ctx->major);
238
239 if ((ctx->major = gss_acquire_cred(&ctx->minor,
240 ctx->name, 0, oidset, GSS_C_ACCEPT, &ctx->creds, NULL, NULL)))
241 ssh_gssapi_error(ctx);
242
243 gss_release_oid_set(&status, &oidset);
244 return (ctx->major);
245}
246
247OM_uint32
248ssh_gssapi_server_ctx(Gssctxt **ctx, gss_OID oid) {
249 if (*ctx)
250 ssh_gssapi_delete_ctx(ctx);
251 ssh_gssapi_build_ctx(ctx);
252 ssh_gssapi_set_oid(*ctx, oid);
253 return (ssh_gssapi_acquire_cred(*ctx));
254}
255
256#endif /* GSSAPI */
diff --git a/gss-serv-krb5.c b/gss-serv-krb5.c
new file mode 100644
index 000000000..d86872258
--- /dev/null
+++ b/gss-serv-krb5.c
@@ -0,0 +1,168 @@
1/* $OpenBSD: gss-serv-krb5.c,v 1.1 2003/08/22 10:56:09 markus Exp $ */
2
3/*
4 * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#include "includes.h"
28
29#ifdef GSSAPI
30#ifdef KRB5
31
32#include "auth.h"
33#include "xmalloc.h"
34#include "log.h"
35#include "servconf.h"
36
37#include "ssh-gss.h"
38
39extern ServerOptions options;
40
41#include <krb5.h>
42
43static krb5_context krb_context = NULL;
44
45/* Initialise the krb5 library, for the stuff that GSSAPI won't do */
46
47static int
48ssh_gssapi_krb5_init()
49{
50 krb5_error_code problem;
51
52 if (krb_context != NULL)
53 return 1;
54
55 problem = krb5_init_context(&krb_context);
56 if (problem) {
57 logit("Cannot initialize krb5 context");
58 return 0;
59 }
60 krb5_init_ets(krb_context);
61
62 return 1;
63}
64
65/* Check if this user is OK to login. This only works with krb5 - other
66 * GSSAPI mechanisms will need their own.
67 * Returns true if the user is OK to log in, otherwise returns 0
68 */
69
70static int
71ssh_gssapi_krb5_userok(ssh_gssapi_client *client, char *name)
72{
73 krb5_principal princ;
74 int retval;
75
76 if (ssh_gssapi_krb5_init() == 0)
77 return 0;
78
79 if ((retval = krb5_parse_name(krb_context, client->exportedname.value,
80 &princ))) {
81 logit("krb5_parse_name(): %.100s",
82 krb5_get_err_text(krb_context, retval));
83 return 0;
84 }
85 if (krb5_kuserok(krb_context, princ, name)) {
86 retval = 1;
87 logit("Authorized to %s, krb5 principal %s (krb5_kuserok)",
88 name, (char *)client->displayname.value);
89 } else
90 retval = 0;
91
92 krb5_free_principal(krb_context, princ);
93 return retval;
94}
95
96
97/* This writes out any forwarded credentials from the structure populated
98 * during userauth. Called after we have setuid to the user */
99
100static void
101ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client)
102{
103 krb5_ccache ccache;
104 krb5_error_code problem;
105 krb5_principal princ;
106 OM_uint32 maj_status, min_status;
107
108 if (client->creds == NULL) {
109 debug("No credentials stored");
110 return;
111 }
112
113 if (ssh_gssapi_krb5_init() == 0)
114 return;
115
116 if ((problem = krb5_cc_gen_new(krb_context, &krb5_fcc_ops, &ccache))) {
117 logit("krb5_cc_gen_new(): %.100s",
118 krb5_get_err_text(krb_context, problem));
119 return;
120 }
121
122 if ((problem = krb5_parse_name(krb_context,
123 client->exportedname.value, &princ))) {
124 logit("krb5_parse_name(): %.100s",
125 krb5_get_err_text(krb_context, problem));
126 krb5_cc_destroy(krb_context, ccache);
127 return;
128 }
129
130 if ((problem = krb5_cc_initialize(krb_context, ccache, princ))) {
131 logit("krb5_cc_initialize(): %.100s",
132 krb5_get_err_text(krb_context, problem));
133 krb5_free_principal(krb_context, princ);
134 krb5_cc_destroy(krb_context, ccache);
135 return;
136 }
137
138 krb5_free_principal(krb_context, princ);
139
140 if ((maj_status = gss_krb5_copy_ccache(&min_status,
141 client->creds, ccache))) {
142 logit("gss_krb5_copy_ccache() failed");
143 krb5_cc_destroy(krb_context, ccache);
144 return;
145 }
146
147 client->store.filename = xstrdup(krb5_cc_get_name(krb_context, ccache));
148 client->store.envvar = "KRB5CCNAME";
149 client->store.envval = xstrdup(client->store.filename);
150
151 krb5_cc_close(krb_context, ccache);
152
153 return;
154}
155
156ssh_gssapi_mech gssapi_kerberos_mech = {
157 "toWM5Slw5Ew8Mqkay+al2g==",
158 "Kerberos",
159 {9, "\x2A\x86\x48\x86\xF7\x12\x01\x02\x02"},
160 NULL,
161 &ssh_gssapi_krb5_userok,
162 NULL,
163 &ssh_gssapi_krb5_storecreds
164};
165
166#endif /* KRB5 */
167
168#endif /* GSSAPI */
diff --git a/gss-serv.c b/gss-serv.c
new file mode 100644
index 000000000..42718177d
--- /dev/null
+++ b/gss-serv.c
@@ -0,0 +1,291 @@
1/* $OpenBSD: gss-serv.c,v 1.1 2003/08/22 10:56:09 markus Exp $ */
2
3/*
4 * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#include "includes.h"
28
29#ifdef GSSAPI
30
31#include "bufaux.h"
32#include "compat.h"
33#include "auth.h"
34#include "log.h"
35#include "channels.h"
36#include "session.h"
37#include "servconf.h"
38#include "monitor_wrap.h"
39#include "xmalloc.h"
40#include "getput.h"
41
42#include "ssh-gss.h"
43
44extern ServerOptions options;
45
46static ssh_gssapi_client gssapi_client =
47 { GSS_C_EMPTY_BUFFER, GSS_C_EMPTY_BUFFER,
48 GSS_C_NO_CREDENTIAL, NULL, {NULL, NULL, NULL}};
49
50ssh_gssapi_mech gssapi_null_mech =
51 { NULL, NULL, {0, NULL}, NULL, NULL, NULL, NULL};
52
53#ifdef KRB5
54extern ssh_gssapi_mech gssapi_kerberos_mech;
55#endif
56
57ssh_gssapi_mech* supported_mechs[]= {
58#ifdef KRB5
59 &gssapi_kerberos_mech,
60#endif
61 &gssapi_null_mech,
62};
63
64/* Unpriviledged */
65void
66ssh_gssapi_supported_oids(gss_OID_set *oidset)
67{
68 int i = 0;
69 OM_uint32 min_status;
70 int present;
71 gss_OID_set supported;
72
73 gss_create_empty_oid_set(&min_status, oidset);
74 gss_indicate_mechs(&min_status, &supported);
75
76 while (supported_mechs[i]->name != NULL) {
77 if (GSS_ERROR(gss_test_oid_set_member(&min_status,
78 &supported_mechs[i]->oid, supported, &present)))
79 present = 0;
80 if (present)
81 gss_add_oid_set_member(&min_status,
82 &supported_mechs[i]->oid, oidset);
83 i++;
84 }
85}
86
87
88/* Wrapper around accept_sec_context
89 * Requires that the context contains:
90 * oid
91 * credentials (from ssh_gssapi_acquire_cred)
92 */
93/* Priviledged */
94OM_uint32
95ssh_gssapi_accept_ctx(Gssctxt *ctx, gss_buffer_desc *recv_tok,
96 gss_buffer_desc *send_tok, OM_uint32 *flags)
97{
98 OM_uint32 status;
99 gss_OID mech;
100
101 ctx->major = gss_accept_sec_context(&ctx->minor,
102 &ctx->context, ctx->creds, recv_tok,
103 GSS_C_NO_CHANNEL_BINDINGS, &ctx->client, &mech,
104 send_tok, flags, NULL, &ctx->client_creds);
105
106 if (GSS_ERROR(ctx->major))
107 ssh_gssapi_error(ctx);
108
109 if (ctx->client_creds)
110 debug("Received some client credentials");
111 else
112 debug("Got no client credentials");
113
114 status = ctx->major;
115
116 /* Now, if we're complete and we have the right flags, then
117 * we flag the user as also having been authenticated
118 */
119
120 if (((flags == NULL) || ((*flags & GSS_C_MUTUAL_FLAG) &&
121 (*flags & GSS_C_INTEG_FLAG))) && (ctx->major == GSS_S_COMPLETE)) {
122 if (ssh_gssapi_getclient(ctx, &gssapi_client))
123 fatal("Couldn't convert client name");
124 }
125
126 return (status);
127}
128
129/*
130 * This parses an exported name, extracting the mechanism specific portion
131 * to use for ACL checking. It verifies that the name belongs the mechanism
132 * originally selected.
133 */
134static OM_uint32
135ssh_gssapi_parse_ename(Gssctxt *ctx, gss_buffer_t ename, gss_buffer_t name)
136{
137 char *tok;
138 OM_uint32 offset;
139 OM_uint32 oidl;
140
141 tok=ename->value;
142
143 /*
144 * Check that ename is long enough for all of the fixed length
145 * header, and that the initial ID bytes are correct
146 */
147
148 if (ename->length<6 || memcmp(tok,"\x04\x01", 2)!=0)
149 return GSS_S_FAILURE;
150
151 /*
152 * Extract the OID, and check it. Here GSSAPI breaks with tradition
153 * and does use the OID type and length bytes. To confuse things
154 * there are two lengths - the first including these, and the
155 * second without.
156 */
157
158 oidl = GET_16BIT(tok+2); /* length including next two bytes */
159 oidl = oidl-2; /* turn it into the _real_ length of the variable OID */
160
161 /*
162 * Check the BER encoding for correct type and length, that the
163 * string is long enough and that the OID matches that in our context
164 */
165 if (tok[4] != 0x06 || tok[5] != oidl ||
166 ename->length < oidl+6 ||
167 !ssh_gssapi_check_oid(ctx,tok+6,oidl))
168 return GSS_S_FAILURE;
169
170 offset = oidl+6;
171
172 if (ename->length < offset+4)
173 return GSS_S_FAILURE;
174
175 name->length = GET_32BIT(tok+offset);
176 offset += 4;
177
178 if (ename->length < offset+name->length)
179 return GSS_S_FAILURE;
180
181 name->value = xmalloc(name->length);
182 memcpy(name->value,tok+offset,name->length);
183
184 return GSS_S_COMPLETE;
185}
186
187/* Extract the client details from a given context. This can only reliably
188 * be called once for a context */
189
190/* Priviledged (called from accept_secure_ctx) */
191OM_uint32
192ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_client *client)
193{
194 int i = 0;
195
196 gss_buffer_desc ename;
197
198 client->mech = NULL;
199
200 while (supported_mechs[i]->name != NULL) {
201 if (supported_mechs[i]->oid.length == ctx->oid->length &&
202 (memcmp(supported_mechs[i]->oid.elements,
203 ctx->oid->elements, ctx->oid->length) == 0))
204 client->mech = supported_mechs[i];
205 i++;
206 }
207
208 if (client->mech == NULL)
209 return GSS_S_FAILURE;
210
211 if ((ctx->major = gss_display_name(&ctx->minor, ctx->client,
212 &client->displayname, NULL))) {
213 ssh_gssapi_error(ctx);
214 return (ctx->major);
215 }
216
217 if ((ctx->major = gss_export_name(&ctx->minor, ctx->client,
218 &ename))) {
219 ssh_gssapi_error(ctx);
220 return (ctx->major);
221 }
222
223 if ((ctx->major = ssh_gssapi_parse_ename(ctx,&ename,
224 &client->exportedname))) {
225 return (ctx->major);
226 }
227
228 /* We can't copy this structure, so we just move the pointer to it */
229 client->creds = ctx->client_creds;
230 ctx->client_creds = GSS_C_NO_CREDENTIAL;
231 return (ctx->major);
232}
233
234/* As user - called through fatal cleanup hook */
235void
236ssh_gssapi_cleanup_creds(void *ignored)
237{
238 if (gssapi_client.store.filename != NULL) {
239 /* Unlink probably isn't sufficient */
240 debug("removing gssapi cred file\"%s\"", gssapi_client.store.filename);
241 unlink(gssapi_client.store.filename);
242 }
243}
244
245/* As user */
246void
247ssh_gssapi_storecreds(void)
248{
249 if (gssapi_client.mech && gssapi_client.mech->storecreds) {
250 (*gssapi_client.mech->storecreds)(&gssapi_client);
251 if (options.gss_cleanup_creds)
252 fatal_add_cleanup(ssh_gssapi_cleanup_creds, NULL);
253 } else
254 debug("ssh_gssapi_storecreds: Not a GSSAPI mechanism");
255}
256
257/* This allows GSSAPI methods to do things to the childs environment based
258 * on the passed authentication process and credentials.
259 */
260/* As user */
261void
262ssh_gssapi_do_child(char ***envp, u_int *envsizep)
263{
264
265 if (gssapi_client.store.envvar != NULL &&
266 gssapi_client.store.envval != NULL) {
267
268 debug("Setting %s to %s", gssapi_client.store.envvar,
269 gssapi_client.store.envval);
270 child_set_env(envp, envsizep, gssapi_client.store.envvar,
271 gssapi_client.store.envval);
272 }
273}
274
275/* Priviledged */
276int
277ssh_gssapi_userok(char *user)
278{
279 if (gssapi_client.exportedname.length == 0 ||
280 gssapi_client.exportedname.value == NULL) {
281 debug("No suitable client data");
282 return 0;
283 }
284 if (gssapi_client.mech && gssapi_client.mech->userok)
285 return ((*gssapi_client.mech->userok)(&gssapi_client, user));
286 else
287 debug("ssh_gssapi_userok: Unknown GSSAPI mechanism");
288 return (0);
289}
290
291#endif
diff --git a/monitor.c b/monitor.c
index 80b1a8fba..f90a90461 100644
--- a/monitor.c
+++ b/monitor.c
@@ -25,7 +25,7 @@
25 */ 25 */
26 26
27#include "includes.h" 27#include "includes.h"
28RCSID("$OpenBSD: monitor.c,v 1.45 2003/07/22 13:35:22 markus Exp $"); 28RCSID("$OpenBSD: monitor.c,v 1.46 2003/08/22 10:56:09 markus Exp $");
29 29
30#include <openssl/dh.h> 30#include <openssl/dh.h>
31 31
@@ -59,6 +59,11 @@ RCSID("$OpenBSD: monitor.c,v 1.45 2003/07/22 13:35:22 markus Exp $");
59#include "ssh2.h" 59#include "ssh2.h"
60#include "mpaux.h" 60#include "mpaux.h"
61 61
62#ifdef GSSAPI
63#include "ssh-gss.h"
64static Gssctxt *gsscontext = NULL;
65#endif
66
62/* Imports */ 67/* Imports */
63extern ServerOptions options; 68extern ServerOptions options;
64extern u_int utmp_len; 69extern u_int utmp_len;
@@ -128,6 +133,11 @@ int mm_answer_pam_free_ctx(int, Buffer *);
128#ifdef KRB5 133#ifdef KRB5
129int mm_answer_krb5(int, Buffer *); 134int mm_answer_krb5(int, Buffer *);
130#endif 135#endif
136#ifdef GSSAPI
137int mm_answer_gss_setup_ctx(int, Buffer *);
138int mm_answer_gss_accept_ctx(int, Buffer *);
139int mm_answer_gss_userok(int, Buffer *);
140#endif
131 141
132static Authctxt *authctxt; 142static Authctxt *authctxt;
133static BIGNUM *ssh1_challenge = NULL; /* used for ssh1 rsa auth */ 143static BIGNUM *ssh1_challenge = NULL; /* used for ssh1 rsa auth */
@@ -185,6 +195,11 @@ struct mon_table mon_dispatch_proto20[] = {
185#ifdef KRB5 195#ifdef KRB5
186 {MONITOR_REQ_KRB5, MON_ONCE|MON_AUTH, mm_answer_krb5}, 196 {MONITOR_REQ_KRB5, MON_ONCE|MON_AUTH, mm_answer_krb5},
187#endif 197#endif
198#ifdef GSSAPI
199 {MONITOR_REQ_GSSSETUP, MON_ISAUTH, mm_answer_gss_setup_ctx},
200 {MONITOR_REQ_GSSSTEP, MON_ISAUTH, mm_answer_gss_accept_ctx},
201 {MONITOR_REQ_GSSUSEROK, MON_AUTH, mm_answer_gss_userok},
202#endif
188 {0, 0, NULL} 203 {0, 0, NULL}
189}; 204};
190 205
@@ -357,7 +372,6 @@ monitor_child_postauth(struct monitor *pmonitor)
357 monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); 372 monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
358 monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); 373 monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
359 monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1); 374 monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1);
360
361 } else { 375 } else {
362 mon_dispatch = mon_dispatch_postauth15; 376 mon_dispatch = mon_dispatch_postauth15;
363 monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1); 377 monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1);
@@ -1769,3 +1783,77 @@ monitor_reinit(struct monitor *mon)
1769 mon->m_recvfd = pair[0]; 1783 mon->m_recvfd = pair[0];
1770 mon->m_sendfd = pair[1]; 1784 mon->m_sendfd = pair[1];
1771} 1785}
1786
1787#ifdef GSSAPI
1788int
1789mm_answer_gss_setup_ctx(int socket, Buffer *m)
1790{
1791 gss_OID_desc oid;
1792 OM_uint32 major;
1793 u_int len;
1794
1795 oid.elements = buffer_get_string(m, &len);
1796 oid.length = len;
1797
1798 major = ssh_gssapi_server_ctx(&gsscontext, &oid);
1799
1800 xfree(oid.elements);
1801
1802 buffer_clear(m);
1803 buffer_put_int(m, major);
1804
1805 mm_request_send(socket,MONITOR_ANS_GSSSETUP, m);
1806
1807 /* Now we have a context, enable the step */
1808 monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP, 1);
1809
1810 return (0);
1811}
1812
1813int
1814mm_answer_gss_accept_ctx(int socket, Buffer *m)
1815{
1816 gss_buffer_desc in;
1817 gss_buffer_desc out = GSS_C_EMPTY_BUFFER;
1818 OM_uint32 major,minor;
1819 OM_uint32 flags = 0; /* GSI needs this */
1820
1821 in.value = buffer_get_string(m, &in.length);
1822 major = ssh_gssapi_accept_ctx(gsscontext, &in, &out, &flags);
1823 xfree(in.value);
1824
1825 buffer_clear(m);
1826 buffer_put_int(m, major);
1827 buffer_put_string(m, out.value, out.length);
1828 buffer_put_int(m, flags);
1829 mm_request_send(socket, MONITOR_ANS_GSSSTEP, m);
1830
1831 gss_release_buffer(&minor, &out);
1832
1833 /* Complete - now we can do signing */
1834 if (major==GSS_S_COMPLETE) {
1835 monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP, 0);
1836 monitor_permit(mon_dispatch, MONITOR_REQ_GSSUSEROK, 1);
1837 }
1838 return (0);
1839}
1840
1841int
1842mm_answer_gss_userok(int socket, Buffer *m)
1843{
1844 int authenticated;
1845
1846 authenticated = authctxt->valid && ssh_gssapi_userok(authctxt->user);
1847
1848 buffer_clear(m);
1849 buffer_put_int(m, authenticated);
1850
1851 debug3("%s: sending result %d", __func__, authenticated);
1852 mm_request_send(socket, MONITOR_ANS_GSSUSEROK, m);
1853
1854 auth_method="gssapi";
1855
1856 /* Monitor loop will terminate if authenticated */
1857 return (authenticated);
1858}
1859#endif /* GSSAPI */
diff --git a/monitor.h b/monitor.h
index eeac78e03..da33ed613 100644
--- a/monitor.h
+++ b/monitor.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: monitor.h,v 1.9 2003/07/22 13:35:22 markus Exp $ */ 1/* $OpenBSD: monitor.h,v 1.10 2003/08/22 10:56:09 markus Exp $ */
2 2
3/* 3/*
4 * Copyright 2002 Niels Provos <provos@citi.umich.edu> 4 * Copyright 2002 Niels Provos <provos@citi.umich.edu>
@@ -50,6 +50,9 @@ enum monitor_reqtype {
50 MONITOR_REQ_RSACHALLENGE, MONITOR_ANS_RSACHALLENGE, 50 MONITOR_REQ_RSACHALLENGE, MONITOR_ANS_RSACHALLENGE,
51 MONITOR_REQ_RSARESPONSE, MONITOR_ANS_RSARESPONSE, 51 MONITOR_REQ_RSARESPONSE, MONITOR_ANS_RSARESPONSE,
52 MONITOR_REQ_KRB5, MONITOR_ANS_KRB5, 52 MONITOR_REQ_KRB5, MONITOR_ANS_KRB5,
53 MONITOR_REQ_GSSSETUP, MONITOR_ANS_GSSSETUP,
54 MONITOR_REQ_GSSSTEP, MONITOR_ANS_GSSSTEP,
55 MONITOR_REQ_GSSUSEROK, MONITOR_ANS_GSSUSEROK,
53 MONITOR_REQ_PAM_START, 56 MONITOR_REQ_PAM_START,
54 MONITOR_REQ_PAM_ACCOUNT, MONITOR_ANS_PAM_ACCOUNT, 57 MONITOR_REQ_PAM_ACCOUNT, MONITOR_ANS_PAM_ACCOUNT,
55 MONITOR_REQ_PAM_INIT_CTX, MONITOR_ANS_PAM_INIT_CTX, 58 MONITOR_REQ_PAM_INIT_CTX, MONITOR_ANS_PAM_INIT_CTX,
diff --git a/monitor_wrap.c b/monitor_wrap.c
index 9e7e6b3c3..4073905f6 100644
--- a/monitor_wrap.c
+++ b/monitor_wrap.c
@@ -25,7 +25,7 @@
25 */ 25 */
26 26
27#include "includes.h" 27#include "includes.h"
28RCSID("$OpenBSD: monitor_wrap.c,v 1.28 2003/07/22 13:35:22 markus Exp $"); 28RCSID("$OpenBSD: monitor_wrap.c,v 1.29 2003/08/22 10:56:09 markus Exp $");
29 29
30#include <openssl/bn.h> 30#include <openssl/bn.h>
31#include <openssl/dh.h> 31#include <openssl/dh.h>
@@ -53,6 +53,10 @@ RCSID("$OpenBSD: monitor_wrap.c,v 1.28 2003/07/22 13:35:22 markus Exp $");
53#include "channels.h" 53#include "channels.h"
54#include "session.h" 54#include "session.h"
55 55
56#ifdef GSSAPI
57#include "ssh-gss.h"
58#endif
59
56/* Imports */ 60/* Imports */
57extern int compat20; 61extern int compat20;
58extern Newkeys *newkeys[]; 62extern Newkeys *newkeys[];
@@ -1100,4 +1104,69 @@ mm_auth_krb5(void *ctx, void *argp, char **userp, void *resp)
1100 buffer_free(&m); 1104 buffer_free(&m);
1101 return (success); 1105 return (success);
1102} 1106}
1103#endif 1107#endif /* KRB5 */
1108
1109#ifdef GSSAPI
1110OM_uint32
1111mm_ssh_gssapi_server_ctx(Gssctxt **ctx, gss_OID oid)
1112{
1113 Buffer m;
1114 OM_uint32 major;
1115
1116 /* Client doesn't get to see the context */
1117 *ctx = NULL;
1118
1119 buffer_init(&m);
1120 buffer_put_string(&m, oid->elements, oid->length);
1121
1122 mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSETUP, &m);
1123 mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSETUP, &m);
1124
1125 major = buffer_get_int(&m);
1126
1127 buffer_free(&m);
1128 return (major);
1129}
1130
1131OM_uint32
1132mm_ssh_gssapi_accept_ctx(Gssctxt *ctx, gss_buffer_desc *in,
1133 gss_buffer_desc *out, OM_uint32 *flags)
1134{
1135 Buffer m;
1136 OM_uint32 major;
1137
1138 buffer_init(&m);
1139 buffer_put_string(&m, in->value, in->length);
1140
1141 mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSTEP, &m);
1142 mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSTEP, &m);
1143
1144 major = buffer_get_int(&m);
1145 out->value = buffer_get_string(&m, &out->length);
1146 if (flags)
1147 *flags = buffer_get_int(&m);
1148
1149 buffer_free(&m);
1150
1151 return (major);
1152}
1153
1154int
1155mm_ssh_gssapi_userok(char *user)
1156{
1157 Buffer m;
1158 int authenticated = 0;
1159
1160 buffer_init(&m);
1161
1162 mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSUSEROK, &m);
1163 mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSUSEROK,
1164 &m);
1165
1166 authenticated = buffer_get_int(&m);
1167
1168 buffer_free(&m);
1169 debug3("%s: user %sauthenticated",__func__, authenticated ? "" : "not ");
1170 return (authenticated);
1171}
1172#endif /* GSSAPI */
diff --git a/monitor_wrap.h b/monitor_wrap.h
index ddd42ee28..c6251924a 100644
--- a/monitor_wrap.h
+++ b/monitor_wrap.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: monitor_wrap.h,v 1.9 2003/07/22 13:35:22 markus Exp $ */ 1/* $OpenBSD: monitor_wrap.h,v 1.10 2003/08/22 10:56:09 markus Exp $ */
2 2
3/* 3/*
4 * Copyright 2002 Niels Provos <provos@citi.umich.edu> 4 * Copyright 2002 Niels Provos <provos@citi.umich.edu>
@@ -55,6 +55,14 @@ int mm_auth_rsa_key_allowed(struct passwd *, BIGNUM *, Key **);
55int mm_auth_rsa_verify_response(Key *, BIGNUM *, u_char *); 55int mm_auth_rsa_verify_response(Key *, BIGNUM *, u_char *);
56BIGNUM *mm_auth_rsa_generate_challenge(Key *); 56BIGNUM *mm_auth_rsa_generate_challenge(Key *);
57 57
58#ifdef GSSAPI
59#include "ssh-gss.h"
60OM_uint32 mm_ssh_gssapi_server_ctx(Gssctxt **ctxt, gss_OID oid);
61OM_uint32 mm_ssh_gssapi_accept_ctx(Gssctxt *ctxt,
62 gss_buffer_desc *recv, gss_buffer_desc *send, OM_uint32 *flags);
63int mm_ssh_gssapi_userok(char *user);
64#endif
65
58#ifdef USE_PAM 66#ifdef USE_PAM
59void mm_start_pam(char *); 67void mm_start_pam(char *);
60u_int mm_do_pam_account(void); 68u_int mm_do_pam_account(void);
diff --git a/readconf.c b/readconf.c
index 96ad25a51..9447cb55f 100644
--- a/readconf.c
+++ b/readconf.c
@@ -12,7 +12,7 @@
12 */ 12 */
13 13
14#include "includes.h" 14#include "includes.h"
15RCSID("$OpenBSD: readconf.c,v 1.117 2003/08/13 09:07:09 markus Exp $"); 15RCSID("$OpenBSD: readconf.c,v 1.118 2003/08/22 10:56:09 markus Exp $");
16 16
17#include "ssh.h" 17#include "ssh.h"
18#include "xmalloc.h" 18#include "xmalloc.h"
@@ -105,7 +105,7 @@ typedef enum {
105 oHostKeyAlgorithms, oBindAddress, oSmartcardDevice, 105 oHostKeyAlgorithms, oBindAddress, oSmartcardDevice,
106 oClearAllForwardings, oNoHostAuthenticationForLocalhost, 106 oClearAllForwardings, oNoHostAuthenticationForLocalhost,
107 oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout, 107 oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
108 oAddressFamily, 108 oAddressFamily, oGssAuthentication, oGssDelegateCreds,
109 oDeprecated, oUnsupported 109 oDeprecated, oUnsupported
110} OpCodes; 110} OpCodes;
111 111
@@ -140,6 +140,14 @@ static struct {
140 { "kerberostgtpassing", oUnsupported }, 140 { "kerberostgtpassing", oUnsupported },
141#endif 141#endif
142 { "afstokenpassing", oUnsupported }, 142 { "afstokenpassing", oUnsupported },
143#if defined(GSSAPI)
144 { "gssapiauthentication", oGssAuthentication },
145 { "gssapidelegatecreds", oGssDelegateCreds },
146 { "gssapidelegatecredentials", oGssDelegateCreds },
147#else
148 { "gssapiauthentication", oUnsupported },
149 { "gssapidelegatecredentials", oUnsupported },
150#endif
143 { "fallbacktorsh", oDeprecated }, 151 { "fallbacktorsh", oDeprecated },
144 { "usersh", oDeprecated }, 152 { "usersh", oDeprecated },
145 { "identityfile", oIdentityFile }, 153 { "identityfile", oIdentityFile },
@@ -389,6 +397,14 @@ parse_flag:
389 intptr = &options->kerberos_tgt_passing; 397 intptr = &options->kerberos_tgt_passing;
390 goto parse_flag; 398 goto parse_flag;
391 399
400 case oGssAuthentication:
401 intptr = &options->gss_authentication;
402 goto parse_flag;
403
404 case oGssDelegateCreds:
405 intptr = &options->gss_deleg_creds;
406 goto parse_flag;
407
392 case oBatchMode: 408 case oBatchMode:
393 intptr = &options->batch_mode; 409 intptr = &options->batch_mode;
394 goto parse_flag; 410 goto parse_flag;
@@ -813,6 +829,8 @@ initialize_options(Options * options)
813 options->challenge_response_authentication = -1; 829 options->challenge_response_authentication = -1;
814 options->kerberos_authentication = -1; 830 options->kerberos_authentication = -1;
815 options->kerberos_tgt_passing = -1; 831 options->kerberos_tgt_passing = -1;
832 options->gss_authentication = -1;
833 options->gss_deleg_creds = -1;
816 options->password_authentication = -1; 834 options->password_authentication = -1;
817 options->kbd_interactive_authentication = -1; 835 options->kbd_interactive_authentication = -1;
818 options->kbd_interactive_devices = NULL; 836 options->kbd_interactive_devices = NULL;
@@ -887,6 +905,10 @@ fill_default_options(Options * options)
887 options->kerberos_authentication = 1; 905 options->kerberos_authentication = 1;
888 if (options->kerberos_tgt_passing == -1) 906 if (options->kerberos_tgt_passing == -1)
889 options->kerberos_tgt_passing = 1; 907 options->kerberos_tgt_passing = 1;
908 if (options->gss_authentication == -1)
909 options->gss_authentication = 1;
910 if (options->gss_deleg_creds == -1)
911 options->gss_deleg_creds = 0;
890 if (options->password_authentication == -1) 912 if (options->password_authentication == -1)
891 options->password_authentication = 1; 913 options->password_authentication = 1;
892 if (options->kbd_interactive_authentication == -1) 914 if (options->kbd_interactive_authentication == -1)
diff --git a/readconf.h b/readconf.h
index 6fbf467e5..1100205b8 100644
--- a/readconf.h
+++ b/readconf.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: readconf.h,v 1.53 2003/08/13 08:46:30 markus Exp $ */ 1/* $OpenBSD: readconf.h,v 1.54 2003/08/22 10:56:09 markus Exp $ */
2 2
3/* 3/*
4 * Author: Tatu Ylonen <ylo@cs.hut.fi> 4 * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -42,6 +42,8 @@ typedef struct {
42 /* Try S/Key or TIS, authentication. */ 42 /* Try S/Key or TIS, authentication. */
43 int kerberos_authentication; /* Try Kerberos authentication. */ 43 int kerberos_authentication; /* Try Kerberos authentication. */
44 int kerberos_tgt_passing; /* Try Kerberos TGT passing. */ 44 int kerberos_tgt_passing; /* Try Kerberos TGT passing. */
45 int gss_authentication; /* Try GSS authentication */
46 int gss_deleg_creds; /* Delegate GSS credentials */
45 int password_authentication; /* Try password 47 int password_authentication; /* Try password
46 * authentication. */ 48 * authentication. */
47 int kbd_interactive_authentication; /* Try keyboard-interactive auth. */ 49 int kbd_interactive_authentication; /* Try keyboard-interactive auth. */
diff --git a/servconf.c b/servconf.c
index 09fdbf424..e13309388 100644
--- a/servconf.c
+++ b/servconf.c
@@ -10,7 +10,7 @@
10 */ 10 */
11 11
12#include "includes.h" 12#include "includes.h"
13RCSID("$OpenBSD: servconf.c,v 1.124 2003/08/13 08:46:30 markus Exp $"); 13RCSID("$OpenBSD: servconf.c,v 1.125 2003/08/22 10:56:09 markus Exp $");
14 14
15#include "ssh.h" 15#include "ssh.h"
16#include "log.h" 16#include "log.h"
@@ -73,6 +73,8 @@ initialize_server_options(ServerOptions *options)
73 options->kerberos_or_local_passwd = -1; 73 options->kerberos_or_local_passwd = -1;
74 options->kerberos_ticket_cleanup = -1; 74 options->kerberos_ticket_cleanup = -1;
75 options->kerberos_tgt_passing = -1; 75 options->kerberos_tgt_passing = -1;
76 options->gss_authentication=-1;
77 options->gss_cleanup_creds = -1;
76 options->password_authentication = -1; 78 options->password_authentication = -1;
77 options->kbd_interactive_authentication = -1; 79 options->kbd_interactive_authentication = -1;
78 options->challenge_response_authentication = -1; 80 options->challenge_response_authentication = -1;
@@ -182,6 +184,10 @@ fill_default_server_options(ServerOptions *options)
182 options->kerberos_ticket_cleanup = 1; 184 options->kerberos_ticket_cleanup = 1;
183 if (options->kerberos_tgt_passing == -1) 185 if (options->kerberos_tgt_passing == -1)
184 options->kerberos_tgt_passing = 0; 186 options->kerberos_tgt_passing = 0;
187 if (options->gss_authentication == -1)
188 options->gss_authentication = 0;
189 if (options->gss_cleanup_creds == -1)
190 options->gss_cleanup_creds = 1;
185 if (options->password_authentication == -1) 191 if (options->password_authentication == -1)
186 options->password_authentication = 1; 192 options->password_authentication = 1;
187 if (options->kbd_interactive_authentication == -1) 193 if (options->kbd_interactive_authentication == -1)
@@ -259,6 +265,7 @@ typedef enum {
259 sBanner, sUseDNS, sHostbasedAuthentication, 265 sBanner, sUseDNS, sHostbasedAuthentication,
260 sHostbasedUsesNameFromPacketOnly, sClientAliveInterval, 266 sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
261 sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2, 267 sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2,
268 sGssAuthentication, sGssCleanupCreds,
262 sUsePrivilegeSeparation, 269 sUsePrivilegeSeparation,
263 sDeprecated, sUnsupported 270 sDeprecated, sUnsupported
264} ServerOpCodes; 271} ServerOpCodes;
@@ -305,6 +312,13 @@ static struct {
305 { "kerberostgtpassing", sUnsupported }, 312 { "kerberostgtpassing", sUnsupported },
306#endif 313#endif
307 { "afstokenpassing", sUnsupported }, 314 { "afstokenpassing", sUnsupported },
315#ifdef GSSAPI
316 { "gssapiauthentication", sGssAuthentication },
317 { "gssapicleanupcreds", sGssCleanupCreds },
318#else
319 { "gssapiauthentication", sUnsupported },
320 { "gssapicleanupcreds", sUnsupported },
321#endif
308 { "passwordauthentication", sPasswordAuthentication }, 322 { "passwordauthentication", sPasswordAuthentication },
309 { "kbdinteractiveauthentication", sKbdInteractiveAuthentication }, 323 { "kbdinteractiveauthentication", sKbdInteractiveAuthentication },
310 { "challengeresponseauthentication", sChallengeResponseAuthentication }, 324 { "challengeresponseauthentication", sChallengeResponseAuthentication },
@@ -623,6 +637,14 @@ parse_flag:
623 intptr = &options->kerberos_tgt_passing; 637 intptr = &options->kerberos_tgt_passing;
624 goto parse_flag; 638 goto parse_flag;
625 639
640 case sGssAuthentication:
641 intptr = &options->gss_authentication;
642 goto parse_flag;
643
644 case sGssCleanupCreds:
645 intptr = &options->gss_cleanup_creds;
646 goto parse_flag;
647
626 case sPasswordAuthentication: 648 case sPasswordAuthentication:
627 intptr = &options->password_authentication; 649 intptr = &options->password_authentication;
628 goto parse_flag; 650 goto parse_flag;
diff --git a/servconf.h b/servconf.h
index 42bcda757..f86cb2209 100644
--- a/servconf.h
+++ b/servconf.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: servconf.h,v 1.63 2003/08/13 08:46:30 markus Exp $ */ 1/* $OpenBSD: servconf.h,v 1.64 2003/08/22 10:56:09 markus Exp $ */
2 2
3/* 3/*
4 * Author: Tatu Ylonen <ylo@cs.hut.fi> 4 * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -82,6 +82,8 @@ typedef struct {
82 * file on logout. */ 82 * file on logout. */
83 int kerberos_tgt_passing; /* If true, permit Kerberos TGT 83 int kerberos_tgt_passing; /* If true, permit Kerberos TGT
84 * passing. */ 84 * passing. */
85 int gss_authentication; /* If true, permit GSSAPI authentication */
86 int gss_cleanup_creds; /* If true, destroy cred cache on logout */
85 int password_authentication; /* If true, permit password 87 int password_authentication; /* If true, permit password
86 * authentication. */ 88 * authentication. */
87 int kbd_interactive_authentication; /* If true, permit */ 89 int kbd_interactive_authentication; /* If true, permit */
diff --git a/session.c b/session.c
index 20c4b8a97..3593a3ff5 100644
--- a/session.c
+++ b/session.c
@@ -33,7 +33,7 @@
33 */ 33 */
34 34
35#include "includes.h" 35#include "includes.h"
36RCSID("$OpenBSD: session.c,v 1.160 2003/08/13 08:33:02 markus Exp $"); 36RCSID("$OpenBSD: session.c,v 1.161 2003/08/22 10:56:09 markus Exp $");
37 37
38#include "ssh.h" 38#include "ssh.h"
39#include "ssh1.h" 39#include "ssh1.h"
@@ -58,6 +58,10 @@ RCSID("$OpenBSD: session.c,v 1.160 2003/08/13 08:33:02 markus Exp $");
58#include "session.h" 58#include "session.h"
59#include "monitor_wrap.h" 59#include "monitor_wrap.h"
60 60
61#ifdef GSSAPI
62#include "ssh-gss.h"
63#endif
64
61/* func */ 65/* func */
62 66
63Session *session_new(void); 67Session *session_new(void);
@@ -424,6 +428,12 @@ do_exec_no_pty(Session *s, const char *command)
424 } 428 }
425#endif /* USE_PAM */ 429#endif /* USE_PAM */
426 430
431#ifdef GSSAPI
432 temporarily_use_uid(s->pw);
433 ssh_gssapi_storecreds();
434 restore_uid();
435#endif
436
427 /* Fork the child. */ 437 /* Fork the child. */
428 if ((pid = fork()) == 0) { 438 if ((pid = fork()) == 0) {
429 fatal_remove_all_cleanups(); 439 fatal_remove_all_cleanups();
@@ -550,6 +560,12 @@ do_exec_pty(Session *s, const char *command)
550 } 560 }
551#endif 561#endif
552 562
563#ifdef GSSAPI
564 temporarily_use_uid(s->pw);
565 ssh_gssapi_storecreds();
566 restore_uid();
567#endif
568
553 /* Fork the child. */ 569 /* Fork the child. */
554 if ((pid = fork()) == 0) { 570 if ((pid = fork()) == 0) {
555 fatal_remove_all_cleanups(); 571 fatal_remove_all_cleanups();
@@ -807,7 +823,7 @@ check_quietlogin(Session *s, const char *command)
807 * Sets the value of the given variable in the environment. If the variable 823 * Sets the value of the given variable in the environment. If the variable
808 * already exists, its value is overriden. 824 * already exists, its value is overriden.
809 */ 825 */
810static void 826void
811child_set_env(char ***envp, u_int *envsizep, const char *name, 827child_set_env(char ***envp, u_int *envsizep, const char *name,
812 const char *value) 828 const char *value)
813{ 829{
@@ -934,6 +950,13 @@ do_setup_env(Session *s, const char *shell)
934 copy_environment(environ, &env, &envsize); 950 copy_environment(environ, &env, &envsize);
935#endif 951#endif
936 952
953#ifdef GSSAPI
954 /* Allow any GSSAPI methods that we've used to alter
955 * the childs environment as they see fit
956 */
957 ssh_gssapi_do_child(&env, &envsize);
958#endif
959
937 if (!options.use_login) { 960 if (!options.use_login) {
938 /* Set basic environment. */ 961 /* Set basic environment. */
939 child_set_env(&env, &envsize, "USER", pw->pw_name); 962 child_set_env(&env, &envsize, "USER", pw->pw_name);
@@ -2088,4 +2111,8 @@ static void
2088do_authenticated2(Authctxt *authctxt) 2111do_authenticated2(Authctxt *authctxt)
2089{ 2112{
2090 server_loop2(authctxt); 2113 server_loop2(authctxt);
2114#if defined(GSSAPI)
2115 if (options.gss_cleanup_creds)
2116 ssh_gssapi_cleanup_creds(NULL);
2117#endif
2091} 2118}
diff --git a/session.h b/session.h
index d3ddfab75..525e47f64 100644
--- a/session.h
+++ b/session.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: session.h,v 1.19 2002/06/30 21:59:45 deraadt Exp $ */ 1/* $OpenBSD: session.h,v 1.20 2003/08/22 10:56:09 markus Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. 4 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
@@ -68,4 +68,7 @@ Session *session_new(void);
68Session *session_by_tty(char *); 68Session *session_by_tty(char *);
69void session_close(Session *); 69void session_close(Session *);
70void do_setusercontext(struct passwd *); 70void do_setusercontext(struct passwd *);
71void child_set_env(char ***envp, u_int *envsizep, const char *name,
72 const char *value);
73
71#endif 74#endif
diff --git a/ssh-gss.h b/ssh-gss.h
new file mode 100644
index 000000000..263e51b94
--- /dev/null
+++ b/ssh-gss.h
@@ -0,0 +1,109 @@
1/*
2 * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
20 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 */
24
25#ifndef _SSH_GSS_H
26#define _SSH_GSS_H
27
28#ifdef GSSAPI
29
30#include "buffer.h"
31
32#include <gssapi.h>
33
34/* draft-ietf-secsh-gsskeyex-06 */
35#define SSH2_MSG_USERAUTH_GSSAPI_RESPONSE 60
36#define SSH2_MSG_USERAUTH_GSSAPI_TOKEN 61
37#define SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE 63
38#define SSH2_MSG_USERAUTH_GSSAPI_ERROR 64
39#define SSH2_MSG_USERAUTH_GSSAPI_ERRTOK 65
40
41#define SSH_GSS_OIDTYPE 0x06
42
43typedef struct {
44 char *filename;
45 char *envvar;
46 char *envval;
47 void *data;
48} ssh_gssapi_ccache;
49
50typedef struct {
51 gss_buffer_desc displayname;
52 gss_buffer_desc exportedname;
53 gss_cred_id_t creds;
54 struct ssh_gssapi_mech_struct *mech;
55 ssh_gssapi_ccache store;
56} ssh_gssapi_client;
57
58typedef struct ssh_gssapi_mech_struct {
59 char *enc_name;
60 char *name;
61 gss_OID_desc oid;
62 int (*dochild) (ssh_gssapi_client *);
63 int (*userok) (ssh_gssapi_client *, char *);
64 int (*localname) (ssh_gssapi_client *, char **);
65 void (*storecreds) (ssh_gssapi_client *);
66} ssh_gssapi_mech;
67
68typedef struct {
69 OM_uint32 major; /* both */
70 OM_uint32 minor; /* both */
71 gss_ctx_id_t context; /* both */
72 gss_name_t name; /* both */
73 gss_OID oid; /* client */
74 gss_cred_id_t creds; /* server */
75 gss_name_t client; /* server */
76 gss_cred_id_t client_creds; /* server */
77} Gssctxt;
78
79extern ssh_gssapi_mech *supported_mechs[];
80
81int ssh_gssapi_check_oid(Gssctxt *ctx, void *data, size_t len);
82void ssh_gssapi_set_oid_data(Gssctxt *ctx, void *data, size_t len);
83void ssh_gssapi_set_oid(Gssctxt *ctx, gss_OID oid);
84void ssh_gssapi_supported_oids(gss_OID_set *oidset);
85ssh_gssapi_mech *ssh_gssapi_get_ctype(Gssctxt *ctxt);
86
87OM_uint32 ssh_gssapi_import_name(Gssctxt *ctx, const char *host);
88OM_uint32 ssh_gssapi_acquire_cred(Gssctxt *ctx);
89OM_uint32 ssh_gssapi_init_ctx(Gssctxt *ctx, int deleg_creds,
90 gss_buffer_desc *recv_tok, gss_buffer_desc *send_tok, OM_uint32 *flags);
91OM_uint32 ssh_gssapi_accept_ctx(Gssctxt *ctx,
92 gss_buffer_desc *recv_tok, gss_buffer_desc *send_tok, OM_uint32 *flags);
93OM_uint32 ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_client *);
94void ssh_gssapi_error(Gssctxt *ctx);
95char *ssh_gssapi_last_error(Gssctxt *ctxt, OM_uint32 *maj, OM_uint32 *min);
96void ssh_gssapi_build_ctx(Gssctxt **ctx);
97void ssh_gssapi_delete_ctx(Gssctxt **ctx);
98OM_uint32 ssh_gssapi_server_ctx(Gssctxt **ctx, gss_OID oid);
99
100/* In the server */
101int ssh_gssapi_userok(char *name);
102
103void ssh_gssapi_do_child(char ***envp, u_int *envsizep);
104void ssh_gssapi_cleanup_creds(void *ignored);
105void ssh_gssapi_storecreds(void);
106
107#endif /* GSSAPI */
108
109#endif /* _SSH_GSS_H */
diff --git a/ssh_config.5 b/ssh_config.5
index fb341d79b..f99562b96 100644
--- a/ssh_config.5
+++ b/ssh_config.5
@@ -34,7 +34,7 @@
34.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 34.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
35.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36.\" 36.\"
37.\" $OpenBSD: ssh_config.5,v 1.17 2003/08/13 08:46:31 markus Exp $ 37.\" $OpenBSD: ssh_config.5,v 1.18 2003/08/22 10:56:09 markus Exp $
38.Dd September 25, 1999 38.Dd September 25, 1999
39.Dt SSH_CONFIG 5 39.Dt SSH_CONFIG 5
40.Os 40.Os
@@ -331,6 +331,18 @@ The default is
331Specifies a file to use for the global 331Specifies a file to use for the global
332host key database instead of 332host key database instead of
333.Pa /etc/ssh/ssh_known_hosts . 333.Pa /etc/ssh/ssh_known_hosts .
334.It Cm GSSAPIAuthentication
335Specifies whether authentication based on GSSAPI may be used, either using
336the result of a successful key exchange, or using GSSAPI user
337authentication.
338The default is
339.Dq yes .
340Note that this option applies to protocol version 2 only.
341.It Cm GSSAPIDelegateCredentials
342Forward (delegate) credentials to the server.
343The default is
344.Dq no .
345Note that this option applies to protocol version 2 only.
334.It Cm HostbasedAuthentication 346.It Cm HostbasedAuthentication
335Specifies whether to try rhosts based authentication with public key 347Specifies whether to try rhosts based authentication with public key
336authentication. 348authentication.
diff --git a/sshconnect2.c b/sshconnect2.c
index 6a0bd409a..c71ad506b 100644
--- a/sshconnect2.c
+++ b/sshconnect2.c
@@ -23,7 +23,7 @@
23 */ 23 */
24 24
25#include "includes.h" 25#include "includes.h"
26RCSID("$OpenBSD: sshconnect2.c,v 1.120 2003/06/24 08:23:46 markus Exp $"); 26RCSID("$OpenBSD: sshconnect2.c,v 1.121 2003/08/22 10:56:09 markus Exp $");
27 27
28#ifdef KRB5 28#ifdef KRB5
29#include <krb5.h> 29#include <krb5.h>
@@ -57,6 +57,10 @@ RCSID("$OpenBSD: sshconnect2.c,v 1.120 2003/06/24 08:23:46 markus Exp $");
57#include "msg.h" 57#include "msg.h"
58#include "pathnames.h" 58#include "pathnames.h"
59 59
60#ifdef GSSAPI
61#include "ssh-gss.h"
62#endif
63
60/* import */ 64/* import */
61extern char *client_version_string; 65extern char *client_version_string;
62extern char *server_version_string; 66extern char *server_version_string;
@@ -178,6 +182,8 @@ struct Authctxt {
178 Sensitive *sensitive; 182 Sensitive *sensitive;
179 /* kbd-interactive */ 183 /* kbd-interactive */
180 int info_req_seen; 184 int info_req_seen;
185 /* generic */
186 void *methoddata;
181}; 187};
182struct Authmethod { 188struct Authmethod {
183 char *name; /* string to compare against server's list */ 189 char *name; /* string to compare against server's list */
@@ -201,6 +207,15 @@ int userauth_kbdint(Authctxt *);
201int userauth_hostbased(Authctxt *); 207int userauth_hostbased(Authctxt *);
202int userauth_kerberos(Authctxt *); 208int userauth_kerberos(Authctxt *);
203 209
210#ifdef GSSAPI
211int userauth_gssapi(Authctxt *authctxt);
212void input_gssapi_response(int type, u_int32_t, void *);
213void input_gssapi_token(int type, u_int32_t, void *);
214void input_gssapi_hash(int type, u_int32_t, void *);
215void input_gssapi_error(int, u_int32_t, void *);
216void input_gssapi_errtok(int, u_int32_t, void *);
217#endif
218
204void userauth(Authctxt *, char *); 219void userauth(Authctxt *, char *);
205 220
206static int sign_and_send_pubkey(Authctxt *, Identity *); 221static int sign_and_send_pubkey(Authctxt *, Identity *);
@@ -213,6 +228,12 @@ static Authmethod *authmethod_lookup(const char *name);
213static char *authmethods_get(void); 228static char *authmethods_get(void);
214 229
215Authmethod authmethods[] = { 230Authmethod authmethods[] = {
231#ifdef GSSAPI
232 {"gssapi",
233 userauth_gssapi,
234 &options.gss_authentication,
235 NULL},
236#endif
216 {"hostbased", 237 {"hostbased",
217 userauth_hostbased, 238 userauth_hostbased,
218 &options.hostbased_authentication, 239 &options.hostbased_authentication,
@@ -283,6 +304,7 @@ ssh_userauth2(const char *local_user, const char *server_user, char *host,
283 authctxt.success = 0; 304 authctxt.success = 0;
284 authctxt.method = authmethod_lookup("none"); 305 authctxt.method = authmethod_lookup("none");
285 authctxt.authlist = NULL; 306 authctxt.authlist = NULL;
307 authctxt.methoddata = NULL;
286 authctxt.sensitive = sensitive; 308 authctxt.sensitive = sensitive;
287 authctxt.info_req_seen = 0; 309 authctxt.info_req_seen = 0;
288 if (authctxt.method == NULL) 310 if (authctxt.method == NULL)
@@ -306,6 +328,10 @@ ssh_userauth2(const char *local_user, const char *server_user, char *host,
306void 328void
307userauth(Authctxt *authctxt, char *authlist) 329userauth(Authctxt *authctxt, char *authlist)
308{ 330{
331 if (authctxt->methoddata) {
332 xfree(authctxt->methoddata);
333 authctxt->methoddata = NULL;
334 }
309 if (authlist == NULL) { 335 if (authlist == NULL) {
310 authlist = authctxt->authlist; 336 authlist = authctxt->authlist;
311 } else { 337 } else {
@@ -361,6 +387,8 @@ input_userauth_success(int type, u_int32_t seq, void *ctxt)
361 fatal("input_userauth_success: no authentication context"); 387 fatal("input_userauth_success: no authentication context");
362 if (authctxt->authlist) 388 if (authctxt->authlist)
363 xfree(authctxt->authlist); 389 xfree(authctxt->authlist);
390 if (authctxt->methoddata)
391 xfree(authctxt->methoddata);
364 authctxt->success = 1; /* break out */ 392 authctxt->success = 1; /* break out */
365} 393}
366 394
@@ -449,6 +477,228 @@ done:
449 userauth(authctxt, NULL); 477 userauth(authctxt, NULL);
450} 478}
451 479
480#ifdef GSSAPI
481int
482userauth_gssapi(Authctxt *authctxt)
483{
484 Gssctxt *gssctxt = NULL;
485 static gss_OID_set supported = NULL;
486 static int mech = 0;
487 OM_uint32 min;
488 int ok = 0;
489
490 /* Try one GSSAPI method at a time, rather than sending them all at
491 * once. */
492
493 if (supported == NULL)
494 gss_indicate_mechs(&min, &supported);
495
496 /* Check to see if the mechanism is usable before we offer it */
497 while (mech<supported->count && !ok) {
498 if (gssctxt)
499 ssh_gssapi_delete_ctx(&gssctxt);
500 ssh_gssapi_build_ctx(&gssctxt);
501 ssh_gssapi_set_oid(gssctxt, &supported->elements[mech]);
502
503 /* My DER encoding requires length<128 */
504 if (supported->elements[mech].length < 128 &&
505 !GSS_ERROR(ssh_gssapi_import_name(gssctxt,
506 authctxt->host))) {
507 ok = 1; /* Mechanism works */
508 } else {
509 mech++;
510 }
511 }
512
513 if (!ok) return 0;
514
515 authctxt->methoddata=(void *)gssctxt;
516
517 packet_start(SSH2_MSG_USERAUTH_REQUEST);
518 packet_put_cstring(authctxt->server_user);
519 packet_put_cstring(authctxt->service);
520 packet_put_cstring(authctxt->method->name);
521
522 packet_put_int(1);
523
524 /* Some servers encode the OID incorrectly (as we used to) */
525 if (datafellows & SSH_BUG_GSSAPI_BER) {
526 packet_put_string(supported->elements[mech].elements,
527 supported->elements[mech].length);
528 } else {
529 packet_put_int((supported->elements[mech].length)+2);
530 packet_put_char(SSH_GSS_OIDTYPE);
531 packet_put_char(supported->elements[mech].length);
532 packet_put_raw(supported->elements[mech].elements,
533 supported->elements[mech].length);
534 }
535
536 packet_send();
537
538 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_RESPONSE, &input_gssapi_response);
539 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, &input_gssapi_token);
540 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERROR, &input_gssapi_error);
541 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, &input_gssapi_errtok);
542
543 mech++; /* Move along to next candidate */
544
545 return 1;
546}
547
548void
549input_gssapi_response(int type, u_int32_t plen, void *ctxt)
550{
551 Authctxt *authctxt = ctxt;
552 Gssctxt *gssctxt;
553 OM_uint32 status, ms;
554 int oidlen;
555 char *oidv;
556 gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER;
557
558 if (authctxt == NULL)
559 fatal("input_gssapi_response: no authentication context");
560 gssctxt = authctxt->methoddata;
561
562 /* Setup our OID */
563 oidv = packet_get_string(&oidlen);
564
565 if (datafellows & SSH_BUG_GSSAPI_BER) {
566 if (!ssh_gssapi_check_oid(gssctxt, oidv, oidlen))
567 fatal("Server returned different OID than expected");
568 } else {
569 if(oidv[0] != SSH_GSS_OIDTYPE || oidv[1] != oidlen-2) {
570 debug("Badly encoded mechanism OID received");
571 userauth(authctxt, NULL);
572 xfree(oidv);
573 return;
574 }
575 if (!ssh_gssapi_check_oid(gssctxt, oidv+2, oidlen-2))
576 fatal("Server returned different OID than expected");
577 }
578
579 packet_check_eom();
580
581 xfree(oidv);
582
583 status = ssh_gssapi_init_ctx(gssctxt, options.gss_deleg_creds,
584 GSS_C_NO_BUFFER, &send_tok, NULL);
585 if (GSS_ERROR(status)) {
586 if (send_tok.length > 0) {
587 packet_start(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK);
588 packet_put_string(send_tok.value, send_tok.length);
589 packet_send();
590 gss_release_buffer(&ms, &send_tok);
591 }
592 /* Start again with next method on list */
593 debug("Trying to start again");
594 userauth(authctxt, NULL);
595 return;
596 }
597
598 /* We must have data to send */
599 packet_start(SSH2_MSG_USERAUTH_GSSAPI_TOKEN);
600 packet_put_string(send_tok.value, send_tok.length);
601 packet_send();
602 gss_release_buffer(&ms, &send_tok);
603}
604
605void
606input_gssapi_token(int type, u_int32_t plen, void *ctxt)
607{
608 Authctxt *authctxt = ctxt;
609 Gssctxt *gssctxt;
610 gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER;
611 gss_buffer_desc recv_tok;
612 OM_uint32 status, ms;
613 u_int slen;
614
615 if (authctxt == NULL)
616 fatal("input_gssapi_response: no authentication context");
617 gssctxt = authctxt->methoddata;
618
619 recv_tok.value = packet_get_string(&slen);
620 recv_tok.length = slen; /* safe typecast */
621
622 packet_check_eom();
623
624 status=ssh_gssapi_init_ctx(gssctxt, options.gss_deleg_creds,
625 &recv_tok, &send_tok, NULL);
626
627 xfree(recv_tok.value);
628
629 if (GSS_ERROR(status)) {
630 if (send_tok.length > 0) {
631 packet_start(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK);
632 packet_put_string(send_tok.value, send_tok.length);
633 packet_send();
634 gss_release_buffer(&ms, &send_tok);
635 }
636 /* Start again with the next method in the list */
637 userauth(authctxt, NULL);
638 return;
639 }
640
641 if (send_tok.length > 0) {
642 packet_start(SSH2_MSG_USERAUTH_GSSAPI_TOKEN);
643 packet_put_string(send_tok.value, send_tok.length);
644 packet_send();
645 gss_release_buffer(&ms, &send_tok);
646 }
647
648 if (status == GSS_S_COMPLETE) {
649 /* If that succeeded, send a exchange complete message */
650 packet_start(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE);
651 packet_send();
652 }
653}
654
655void
656input_gssapi_errtok(int type, u_int32_t plen, void *ctxt)
657{
658 Authctxt *authctxt = ctxt;
659 Gssctxt *gssctxt;
660 gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER;
661 gss_buffer_desc recv_tok;
662 OM_uint32 status, ms;
663
664 if (authctxt == NULL)
665 fatal("input_gssapi_response: no authentication context");
666 gssctxt = authctxt->methoddata;
667
668 recv_tok.value = packet_get_string(&recv_tok.length);
669
670 packet_check_eom();
671
672 /* Stick it into GSSAPI and see what it says */
673 status = ssh_gssapi_init_ctx(gssctxt, options.gss_deleg_creds,
674 &recv_tok, &send_tok, NULL);
675
676 xfree(recv_tok.value);
677 gss_release_buffer(&ms, &send_tok);
678
679 /* Server will be returning a failed packet after this one */
680}
681
682void
683input_gssapi_error(int type, u_int32_t plen, void *ctxt)
684{
685 OM_uint32 maj, min;
686 char *msg;
687 char *lang;
688
689 maj=packet_get_int();
690 min=packet_get_int();
691 msg=packet_get_string(NULL);
692 lang=packet_get_string(NULL);
693
694 packet_check_eom();
695
696 debug("Server GSSAPI Error:\n%s\n", msg);
697 xfree(msg);
698 xfree(lang);
699}
700#endif /* GSSAPI */
701
452int 702int
453userauth_none(Authctxt *authctxt) 703userauth_none(Authctxt *authctxt)
454{ 704{
diff --git a/sshd_config b/sshd_config
index a2bd2ff60..294539096 100644
--- a/sshd_config
+++ b/sshd_config
@@ -1,4 +1,4 @@
1# $OpenBSD: sshd_config,v 1.63 2003/08/13 08:46:31 markus Exp $ 1# $OpenBSD: sshd_config,v 1.64 2003/08/22 10:56:09 markus Exp $
2 2
3# This is the sshd server system-wide configuration file. See 3# This is the sshd server system-wide configuration file. See
4# sshd_config(5) for more information. 4# sshd_config(5) for more information.
@@ -63,6 +63,10 @@
63#KerberosTicketCleanup yes 63#KerberosTicketCleanup yes
64#KerberosTgtPassing no 64#KerberosTgtPassing no
65 65
66# GSSAPI options
67#GSSAPIAuthentication no
68#GSSAPICleanupCreds yes
69
66# Set this to 'yes' to enable PAM authentication (via challenge-response) 70# Set this to 'yes' to enable PAM authentication (via challenge-response)
67# and session processing. Depending on your PAM configuration, this may 71# and session processing. Depending on your PAM configuration, this may
68# bypass the setting of 'PasswordAuthentication' 72# bypass the setting of 'PasswordAuthentication'
diff --git a/sshd_config.5 b/sshd_config.5
index 3d920cc80..8857c673d 100644
--- a/sshd_config.5
+++ b/sshd_config.5
@@ -34,7 +34,7 @@
34.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 34.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
35.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36.\" 36.\"
37.\" $OpenBSD: sshd_config.5,v 1.22 2003/08/13 08:46:31 markus Exp $ 37.\" $OpenBSD: sshd_config.5,v 1.23 2003/08/22 10:56:09 markus Exp $
38.Dd September 25, 1999 38.Dd September 25, 1999
39.Dt SSHD_CONFIG 5 39.Dt SSHD_CONFIG 5
40.Os 40.Os
@@ -225,6 +225,19 @@ or
225.Dq no . 225.Dq no .
226The default is 226The default is
227.Dq no . 227.Dq no .
228.It Cm GSSAPIAuthentication
229Specifies whether authentication based on GSSAPI may be used, either using
230the result of a successful key exchange, or using GSSAPI user
231authentication.
232The default is
233.Dq no .
234Note that this option applies to protocol version 2 only.
235.It Cm GSSAPICleanupCredentials
236Specifies whether to automatically destroy the user's credentials cache
237on logout.
238The default is
239.Dq yes .
240Note that this option applies to protocol version 2 only.
228.It Cm HostbasedAuthentication 241.It Cm HostbasedAuthentication
229Specifies whether rhosts or /etc/hosts.equiv authentication together 242Specifies whether rhosts or /etc/hosts.equiv authentication together
230with successful public key client host authentication is allowed 243with successful public key client host authentication is allowed