]>
Commit | Line | Data |
---|---|---|
1 | /* $Id$ | |
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("$Header$"); | |
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(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 | } |