Annotation of src/usr.bin/ssh/auth-krb5.c, Revision 1.5
1.1 dugsong 1: /*
2: * Kerberos v5 authentication and ticket-passing routines.
3: *
4: * $FreeBSD: src/crypto/openssh/auth-krb5.c,v 1.6 2001/02/13 16:58:04 assar Exp $
1.5 ! markus 5: * $OpenBSD: auth-krb5.c,v 1.4 2002/01/27 15:12:09 markus Exp $
1.1 dugsong 6: */
7:
8: #include "includes.h"
9: #include "ssh.h"
10: #include "ssh1.h"
11: #include "packet.h"
12: #include "xmalloc.h"
13: #include "log.h"
14: #include "servconf.h"
15: #include "uidswap.h"
16: #include "auth.h"
17:
18: #ifdef KRB5
19: #include <krb5.h>
20:
21: extern ServerOptions options;
22:
23: static int
24: krb5_init(void *context)
25: {
26: Authctxt *authctxt = (Authctxt *)context;
27: krb5_error_code problem;
28: static int cleanup_registered = 0;
1.3 deraadt 29:
1.1 dugsong 30: if (authctxt->krb5_ctx == NULL) {
31: problem = krb5_init_context(&authctxt->krb5_ctx);
32: if (problem)
33: return (problem);
34: krb5_init_ets(authctxt->krb5_ctx);
35: }
36: if (!cleanup_registered) {
37: fatal_add_cleanup(krb5_cleanup_proc, authctxt);
38: cleanup_registered = 1;
39: }
40: return (0);
41: }
42:
43: /*
44: * Try krb5 authentication. server_user is passed for logging purposes
45: * only, in auth is received ticket, in client is returned principal
46: * from the ticket
47: */
1.3 deraadt 48: int
1.1 dugsong 49: auth_krb5(Authctxt *authctxt, krb5_data *auth, char **client)
50: {
51: krb5_error_code problem;
52: krb5_principal server;
53: krb5_data reply;
54: krb5_ticket *ticket;
1.2 dugsong 55: int fd, ret;
56:
57: ret = 0;
1.1 dugsong 58: server = NULL;
59: ticket = NULL;
60: reply.length = 0;
1.3 deraadt 61:
1.1 dugsong 62: problem = krb5_init(authctxt);
1.3 deraadt 63: if (problem)
1.1 dugsong 64: goto err;
1.3 deraadt 65:
1.1 dugsong 66: problem = krb5_auth_con_init(authctxt->krb5_ctx,
67: &authctxt->krb5_auth_ctx);
68: if (problem)
69: goto err;
1.3 deraadt 70:
1.1 dugsong 71: fd = packet_get_connection_in();
72: problem = krb5_auth_con_setaddrs_from_fd(authctxt->krb5_ctx,
73: authctxt->krb5_auth_ctx, &fd);
74: if (problem)
75: goto err;
1.3 deraadt 76:
1.1 dugsong 77: problem = krb5_sname_to_principal(authctxt->krb5_ctx, NULL, NULL ,
78: KRB5_NT_SRV_HST, &server);
79: if (problem)
80: goto err;
1.3 deraadt 81:
1.1 dugsong 82: problem = krb5_rd_req(authctxt->krb5_ctx, &authctxt->krb5_auth_ctx,
83: auth, server, NULL, NULL, &ticket);
84: if (problem)
85: goto err;
1.3 deraadt 86:
1.1 dugsong 87: problem = krb5_copy_principal(authctxt->krb5_ctx, ticket->client,
88: &authctxt->krb5_user);
89: if (problem)
90: goto err;
1.3 deraadt 91:
1.1 dugsong 92: /* if client wants mutual auth */
93: problem = krb5_mk_rep(authctxt->krb5_ctx, authctxt->krb5_auth_ctx,
94: &reply);
95: if (problem)
96: goto err;
1.3 deraadt 97:
1.1 dugsong 98: /* Check .k5login authorization now. */
99: if (!krb5_kuserok(authctxt->krb5_ctx, authctxt->krb5_user,
100: authctxt->pw->pw_name))
101: goto err;
1.3 deraadt 102:
1.1 dugsong 103: if (client)
104: krb5_unparse_name(authctxt->krb5_ctx, authctxt->krb5_user,
105: client);
1.3 deraadt 106:
1.1 dugsong 107: packet_start(SSH_SMSG_AUTH_KERBEROS_RESPONSE);
108: packet_put_string((char *) reply.data, reply.length);
109: packet_send();
110: packet_write_wait();
1.2 dugsong 111:
112: ret = 1;
1.1 dugsong 113: err:
114: if (server)
115: krb5_free_principal(authctxt->krb5_ctx, server);
116: if (ticket)
117: krb5_free_ticket(authctxt->krb5_ctx, ticket);
118: if (reply.length)
119: xfree(reply.data);
1.3 deraadt 120:
1.5 ! markus 121: if (problem) {
! 122: if (authctxt->krb5_ctx != NULL)
! 123: debug("Kerberos v5 authentication failed: %s",
! 124: krb5_get_err_text(authctxt->krb5_ctx, problem));
! 125: else
! 126: debug("Kerberos v5 authentication failed: %d",
! 127: problem);
! 128: }
1.2 dugsong 129:
130: return (ret);
1.1 dugsong 131: }
132:
133: int
134: auth_krb5_tgt(Authctxt *authctxt, krb5_data *tgt)
135: {
136: krb5_error_code problem;
137: krb5_ccache ccache = NULL;
138: char *pname;
1.3 deraadt 139:
1.1 dugsong 140: if (authctxt->pw == NULL || authctxt->krb5_user == NULL)
141: return (0);
1.3 deraadt 142:
1.1 dugsong 143: temporarily_use_uid(authctxt->pw);
1.3 deraadt 144:
1.1 dugsong 145: problem = krb5_cc_gen_new(authctxt->krb5_ctx, &krb5_fcc_ops, &ccache);
146: if (problem)
147: goto fail;
1.3 deraadt 148:
1.1 dugsong 149: problem = krb5_cc_initialize(authctxt->krb5_ctx, ccache,
150: authctxt->krb5_user);
151: if (problem)
152: goto fail;
1.3 deraadt 153:
1.1 dugsong 154: problem = krb5_rd_cred2(authctxt->krb5_ctx, authctxt->krb5_auth_ctx,
155: ccache, tgt);
156: if (problem)
157: goto fail;
1.3 deraadt 158:
1.1 dugsong 159: authctxt->krb5_fwd_ccache = ccache;
160: ccache = NULL;
1.3 deraadt 161:
1.1 dugsong 162: authctxt->krb5_ticket_file = (char *)krb5_cc_get_name(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache);
1.3 deraadt 163:
1.1 dugsong 164: problem = krb5_unparse_name(authctxt->krb5_ctx, authctxt->krb5_user,
165: &pname);
166: if (problem)
167: goto fail;
1.3 deraadt 168:
1.1 dugsong 169: debug("Kerberos v5 TGT accepted (%s)", pname);
1.3 deraadt 170:
1.1 dugsong 171: restore_uid();
1.3 deraadt 172:
1.1 dugsong 173: return (1);
1.3 deraadt 174:
1.1 dugsong 175: fail:
176: if (problem)
177: debug("Kerberos v5 TGT passing failed: %s",
178: krb5_get_err_text(authctxt->krb5_ctx, problem));
179: if (ccache)
180: krb5_cc_destroy(authctxt->krb5_ctx, ccache);
1.3 deraadt 181:
1.1 dugsong 182: restore_uid();
1.3 deraadt 183:
1.1 dugsong 184: return (0);
185: }
186:
187: int
188: auth_krb5_password(Authctxt *authctxt, const char *password)
189: {
190: krb5_error_code problem;
1.3 deraadt 191:
1.1 dugsong 192: if (authctxt->pw == NULL)
193: return (0);
1.3 deraadt 194:
1.1 dugsong 195: temporarily_use_uid(authctxt->pw);
1.3 deraadt 196:
1.1 dugsong 197: problem = krb5_init(authctxt);
198: if (problem)
199: goto out;
1.3 deraadt 200:
1.1 dugsong 201: problem = krb5_parse_name(authctxt->krb5_ctx, authctxt->pw->pw_name,
202: &authctxt->krb5_user);
203: if (problem)
204: goto out;
1.3 deraadt 205:
1.1 dugsong 206: problem = krb5_cc_gen_new(authctxt->krb5_ctx, &krb5_mcc_ops,
207: &authctxt->krb5_fwd_ccache);
208: if (problem)
209: goto out;
1.3 deraadt 210:
1.1 dugsong 211: problem = krb5_cc_initialize(authctxt->krb5_ctx,
212: authctxt->krb5_fwd_ccache, authctxt->krb5_user);
213: if (problem)
214: goto out;
1.3 deraadt 215:
1.4 markus 216: restore_uid();
1.1 dugsong 217: problem = krb5_verify_user(authctxt->krb5_ctx, authctxt->krb5_user,
218: authctxt->krb5_fwd_ccache, password, 1, NULL);
1.4 markus 219: temporarily_use_uid(authctxt->pw);
220:
1.1 dugsong 221: if (problem)
222: goto out;
1.3 deraadt 223:
1.1 dugsong 224: authctxt->krb5_ticket_file = (char *)krb5_cc_get_name(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache);
1.3 deraadt 225:
1.1 dugsong 226: out:
227: restore_uid();
1.3 deraadt 228:
1.1 dugsong 229: if (problem) {
1.5 ! markus 230: if (authctxt->krb5_ctx != NULL)
! 231: debug("Kerberos password authentication failed: %s",
! 232: krb5_get_err_text(authctxt->krb5_ctx, problem));
! 233: else
! 234: debug("Kerberos password authentication failed: %d",
! 235: problem);
1.3 deraadt 236:
1.1 dugsong 237: krb5_cleanup_proc(authctxt);
1.3 deraadt 238:
1.1 dugsong 239: if (options.kerberos_or_local_passwd)
240: return (-1);
241: else
242: return (0);
243: }
244: return (1);
245: }
246:
247: void
248: krb5_cleanup_proc(void *context)
249: {
250: Authctxt *authctxt = (Authctxt *)context;
1.3 deraadt 251:
1.1 dugsong 252: debug("krb5_cleanup_proc called");
253: if (authctxt->krb5_fwd_ccache) {
254: krb5_cc_destroy(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache);
255: authctxt->krb5_fwd_ccache = NULL;
256: }
257: if (authctxt->krb5_user) {
258: krb5_free_principal(authctxt->krb5_ctx, authctxt->krb5_user);
259: authctxt->krb5_user = NULL;
260: }
261: if (authctxt->krb5_auth_ctx) {
262: krb5_auth_con_free(authctxt->krb5_ctx,
263: authctxt->krb5_auth_ctx);
264: authctxt->krb5_auth_ctx = NULL;
265: }
266: if (authctxt->krb5_ctx) {
267: krb5_free_context(authctxt->krb5_ctx);
268: authctxt->krb5_ctx = NULL;
269: }
270: }
271:
272: #endif /* KRB5 */