]>
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 | #include <krb.h> | |
19 | ||
20 | RCSID("$Header$"); | |
21 | ||
22 | static char service[] = "rcmd"; | |
23 | static char master[] = "sms"; | |
24 | static char qmark[] = "???"; | |
25 | extern des_cblock session; | |
26 | ||
27 | /* | |
28 | * authentication request auth_002: | |
29 | * | |
30 | * >>> (STRING) "auth_002" | |
31 | * <<< (int) 0 | |
32 | * >>> (STRING) ticket | |
33 | * <<< (int) code | |
34 | * <<< (STRING) nonce | |
35 | * >>> (STRING) encrypted nonce | |
36 | * <<< (int) code | |
37 | * | |
38 | */ | |
39 | ||
40 | void auth_002(int conn, char *str) | |
41 | { | |
42 | char aname[ANAME_SZ], ainst[INST_SZ], arealm[REALM_SZ]; | |
43 | AUTH_DAT ad; | |
44 | char *p, *first, *data; | |
45 | size_t size; | |
46 | KTEXT_ST ticket_st; | |
47 | des_key_schedule sched; | |
48 | des_cblock nonce, nonce2; | |
49 | long code; | |
50 | ||
51 | send_ok(conn); | |
52 | ||
53 | recv_string(conn, &data, &size); | |
54 | if (size > sizeof(ticket_st.dat)) | |
55 | { | |
56 | code = KE_RD_AP_UNDEC; | |
57 | com_err(whoami, code, ": authenticator too large"); | |
58 | send_int(conn, code); | |
59 | return; | |
60 | } | |
61 | memcpy(ticket_st.dat, data, size); | |
62 | free(data); | |
63 | ticket_st.mbz = 0; | |
64 | ticket_st.length = size; | |
65 | code = krb_rd_req(&ticket_st, service, krb_get_phost(hostname), 0, | |
66 | &ad, KEYFILE); | |
67 | if (code) | |
68 | { | |
69 | code += ERROR_TABLE_BASE_krb; | |
70 | strcpy(ad.pname, qmark); | |
71 | strcpy(ad.pinst, qmark); | |
72 | strcpy(ad.prealm, qmark); | |
73 | goto auth_failed; | |
74 | } | |
75 | ||
76 | /* If there is an auth record in the config file matching the | |
77 | * authenticator we received, then accept it. If there's no | |
78 | * auth record, assume [master]@[local realm]. | |
79 | */ | |
80 | if ((first = p = config_lookup("auth"))) | |
81 | { | |
82 | do | |
83 | { | |
84 | kname_parse(aname, ainst, arealm, p); | |
85 | if (strcmp(aname, ad.pname) || | |
86 | strcmp(ainst, ad.pinst) || | |
87 | strcmp(arealm, ad.prealm)) | |
88 | p = config_lookup("auth"); | |
89 | else | |
90 | p = first; | |
91 | } | |
92 | while (p != first); | |
93 | } | |
94 | else | |
95 | { | |
96 | strcpy(aname, master); | |
97 | strcpy(ainst, ""); | |
98 | if (krb_get_lrealm(arealm, 1)) | |
99 | strcpy(arealm, KRB_REALM); | |
100 | } | |
101 | code = EPERM; | |
102 | if (strcmp(aname, ad.pname) || | |
103 | strcmp(ainst, ad.pinst) || | |
104 | strcmp(arealm, ad.prealm)) | |
105 | goto auth_failed; | |
106 | ||
107 | send_ok(conn); | |
108 | ||
109 | /* replay protection */ | |
110 | des_random_key(&nonce); | |
111 | send_string(conn, (char *)nonce, sizeof(nonce)); | |
112 | recv_string(conn, &data, &size); | |
113 | des_key_sched(ad.session, sched); | |
114 | des_ecb_encrypt(data, nonce2, sched, 0); | |
115 | free(data); | |
116 | if (memcmp(nonce, nonce2, sizeof(nonce))) | |
117 | goto auth_failed; | |
118 | send_ok(conn); | |
119 | ||
120 | have_authorization = 1; | |
121 | /* Stash away session key */ | |
122 | memcpy(session, ad.session, sizeof(session)); | |
123 | return; | |
124 | ||
125 | auth_failed: | |
126 | com_err(whoami, code, "auth for %s.%s@%s failed", | |
127 | ad.pname, ad.pinst, ad.prealm); | |
128 | send_int(conn, code); | |
129 | } |