1 | /* $Id: auth_002.c 3956 2010-01-05 20:56:56Z zacheiss $ |
---|
2 | * |
---|
3 | * Copyright (C) 1988-1998 by the Massachusetts Institute of Technology. |
---|
4 | * For copying and distribution information, please see the file |
---|
5 | * <mit-copyright.h>. |
---|
6 | */ |
---|
7 | |
---|
8 | #include <mit-copyright.h> |
---|
9 | #include <moira.h> |
---|
10 | #include "update_server.h" |
---|
11 | |
---|
12 | #include <sys/utsname.h> |
---|
13 | |
---|
14 | #include <errno.h> |
---|
15 | #include <stdio.h> |
---|
16 | #include <string.h> |
---|
17 | |
---|
18 | #ifdef HAVE_KRB4 |
---|
19 | #include <krb.h> |
---|
20 | #endif |
---|
21 | |
---|
22 | RCSID("$HeadURL: svn+ssh://svn.mit.edu/moira/trunk/moira/update/auth_002.c $ $Id: auth_002.c 3956 2010-01-05 20:56:56Z zacheiss $"); |
---|
23 | |
---|
24 | static char service[] = "rcmd"; |
---|
25 | static char master[] = "sms"; |
---|
26 | static char qmark[] = "???"; |
---|
27 | #ifdef HAVE_KRB4 |
---|
28 | extern des_cblock session; |
---|
29 | #endif |
---|
30 | |
---|
31 | /* |
---|
32 | * authentication request auth_002: |
---|
33 | * |
---|
34 | * >>> (STRING) "auth_002" |
---|
35 | * <<< (int) 0 |
---|
36 | * >>> (STRING) ticket |
---|
37 | * <<< (int) code |
---|
38 | * <<< (STRING) nonce |
---|
39 | * >>> (STRING) encrypted nonce |
---|
40 | * <<< (int) code |
---|
41 | * |
---|
42 | */ |
---|
43 | |
---|
44 | void auth_002(int conn, char *str) |
---|
45 | { |
---|
46 | #ifdef HAVE_KRB4 |
---|
47 | char aname[ANAME_SZ], ainst[INST_SZ], arealm[REALM_SZ]; |
---|
48 | AUTH_DAT ad; |
---|
49 | char *p, *first, *data; |
---|
50 | size_t size; |
---|
51 | KTEXT_ST ticket_st; |
---|
52 | des_key_schedule sched; |
---|
53 | des_cblock nonce, nonce2; |
---|
54 | long code; |
---|
55 | |
---|
56 | send_ok(conn); |
---|
57 | |
---|
58 | recv_string(conn, &data, &size); |
---|
59 | if (size > sizeof(ticket_st.dat)) |
---|
60 | { |
---|
61 | code = KE_RD_AP_UNDEC; |
---|
62 | com_err(whoami, code, ": authenticator too large"); |
---|
63 | send_int(conn, code); |
---|
64 | return; |
---|
65 | } |
---|
66 | memcpy(ticket_st.dat, data, size); |
---|
67 | free(data); |
---|
68 | ticket_st.mbz = 0; |
---|
69 | ticket_st.length = size; |
---|
70 | code = krb_rd_req(&ticket_st, service, krb_get_phost(hostname), 0, |
---|
71 | &ad, KEYFILE); |
---|
72 | if (code) |
---|
73 | { |
---|
74 | code += ERROR_TABLE_BASE_krb; |
---|
75 | strcpy(ad.pname, qmark); |
---|
76 | strcpy(ad.pinst, qmark); |
---|
77 | strcpy(ad.prealm, qmark); |
---|
78 | goto auth_failed; |
---|
79 | } |
---|
80 | |
---|
81 | /* If there is an auth record in the config file matching the |
---|
82 | * authenticator we received, then accept it. If there's no |
---|
83 | * auth record, assume [master]@[local realm]. |
---|
84 | */ |
---|
85 | if ((first = p = config_lookup("auth"))) |
---|
86 | { |
---|
87 | do |
---|
88 | { |
---|
89 | kname_parse(aname, ainst, arealm, p); |
---|
90 | if (strcmp(aname, ad.pname) || |
---|
91 | strcmp(ainst, ad.pinst) || |
---|
92 | strcmp(arealm, ad.prealm)) |
---|
93 | p = config_lookup("auth"); |
---|
94 | else |
---|
95 | p = first; |
---|
96 | } |
---|
97 | while (p != first); |
---|
98 | } |
---|
99 | else |
---|
100 | { |
---|
101 | strcpy(aname, master); |
---|
102 | strcpy(ainst, ""); |
---|
103 | if (krb_get_lrealm(arealm, 1)) |
---|
104 | strcpy(arealm, KRB_REALM); |
---|
105 | } |
---|
106 | code = EPERM; |
---|
107 | if (strcmp(aname, ad.pname) || |
---|
108 | strcmp(ainst, ad.pinst) || |
---|
109 | strcmp(arealm, ad.prealm)) |
---|
110 | goto auth_failed; |
---|
111 | |
---|
112 | send_ok(conn); |
---|
113 | |
---|
114 | /* replay protection */ |
---|
115 | des_random_key(&nonce); |
---|
116 | send_string(conn, (char *)nonce, sizeof(nonce)); |
---|
117 | recv_string(conn, &data, &size); |
---|
118 | des_key_sched(ad.session, sched); |
---|
119 | des_ecb_encrypt((des_cblock *)data, &nonce2, sched, 0); |
---|
120 | free(data); |
---|
121 | if (memcmp(nonce, nonce2, sizeof(nonce))) |
---|
122 | goto auth_failed; |
---|
123 | send_ok(conn); |
---|
124 | |
---|
125 | have_authorization = 1; |
---|
126 | /* Stash away session key */ |
---|
127 | memcpy(session, ad.session, sizeof(session)); |
---|
128 | return; |
---|
129 | |
---|
130 | auth_failed: |
---|
131 | com_err(whoami, code, "auth for %s.%s@%s failed", |
---|
132 | ad.pname, ad.pinst, ad.prealm); |
---|
133 | send_int(conn, code); |
---|
134 | #else |
---|
135 | send_int(conn, MR_NO_KRB4); |
---|
136 | #endif |
---|
137 | } |
---|