Commit | Line | Data |
---|---|---|
5dc00f89 KF |
1 | /* |
2 | * Copyright (c) 1989 The Regents of the University of California. | |
3 | * All rights reserved. | |
4 | * | |
5 | * Redistribution and use in source and binary forms are permitted | |
6 | * provided that the above copyright notice and this paragraph are | |
7 | * duplicated in all such forms and that any documentation, | |
8 | * advertising materials, and other materials related to such | |
9 | * distribution and use acknowledge that the software was developed | |
10 | * by the University of California, Berkeley. The name of the | |
11 | * University may not be used to endorse or promote products derived | |
12 | * from this software without specific prior written permission. | |
13 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR | |
14 | * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED | |
15 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. | |
16 | */ | |
17 | ||
18 | #ifndef lint | |
19 | static char sccsid[] = "@(#)kpasswdd.c 1.2 (Berkeley) %G%"; | |
20 | #endif /* not lint */ | |
bbb934c5 KF |
21 | |
22 | /* | |
23 | * kpasswdd - update a principal's passwd field in the Kerberos | |
24 | * database. Called from inetd. | |
25 | * K. Fall | |
26 | * 12-Dec-88 | |
27 | */ | |
28 | ||
29 | #include <stdio.h> | |
30 | #include <sys/types.h> | |
31 | #include <sys/time.h> | |
32 | #include <syslog.h> | |
33 | #include <kerberos/krb.h> | |
34 | #include <kerberos/krb_db.h> | |
35 | #include <sys/resource.h> | |
36 | #include <sys/signal.h> | |
37 | #include <netinet/in.h> | |
38 | #include "kpasswd_proto.h" | |
39 | ||
40 | static struct kpasswd_data kpwd_data; | |
41 | static C_Block master_key, key; | |
42 | static Key_schedule master_key_schedule, | |
43 | key_schedule, random_sched; | |
44 | int mkeyversion; | |
45 | AUTH_DAT kdata; | |
46 | static Principal principal_data; | |
47 | static struct update_data ud_data; | |
48 | ||
49 | char inst[INST_SZ]; | |
50 | char version[9]; | |
51 | KTEXT_ST ticket; | |
52 | ||
53 | char *progname; /* for the library */ | |
54 | ||
55 | main() | |
56 | { | |
57 | struct sockaddr_in foreign; | |
58 | int foreign_len = sizeof(foreign); | |
59 | int rval, more; | |
60 | static char name[] = "kpasswdd"; | |
61 | ||
62 | static struct rlimit rl = { 0, 0 }; | |
63 | ||
64 | progname = name; | |
65 | openlog("kpasswdd", LOG_CONS | LOG_PID, LOG_AUTH); | |
66 | ||
67 | signal(SIGHUP, SIG_IGN); | |
68 | signal(SIGINT, SIG_IGN); | |
69 | signal(SIGTSTP, SIG_IGN); | |
70 | if(setrlimit(RLIMIT_CORE, &rl) < 0) { | |
71 | syslog(LOG_ERR, "setrlimit: %m"); | |
72 | exit(1); | |
73 | } | |
74 | ||
75 | if(getpeername(0, &foreign, &foreign_len) < 0) { | |
76 | syslog(LOG_ERR,"getpeername: %m"); | |
77 | exit(1); | |
78 | } | |
79 | ||
80 | strcpy(inst, "*"); | |
81 | rval = krb_recvauth( | |
82 | 0L, /* !MUTUAL */ | |
83 | 0, /* file desc */ | |
84 | &ticket, /* client's ticket */ | |
85 | SERVICE, /* expected service */ | |
86 | inst, /* expected instance */ | |
87 | &foreign, /* foreign addr */ | |
88 | (struct sockaddr_in *) 0, | |
89 | &kdata, | |
90 | "", | |
91 | (bit_64 *) NULL, /* key schedule */ | |
92 | version | |
93 | ); | |
94 | ||
95 | ||
96 | if(rval != KSUCCESS) { | |
97 | syslog(LOG_ERR, "krb_recvauth: %s", krb_err_txt[rval]); | |
98 | cleanup(); | |
99 | exit(1); | |
100 | } | |
101 | ||
102 | ||
103 | /* get master key */ | |
104 | if(kdb_get_master_key(0, master_key, master_key_schedule) != 0) { | |
105 | syslog(LOG_ERR, "couldn't get master key"); | |
106 | cleanup(); | |
107 | exit(1); | |
108 | } | |
109 | ||
110 | mkeyversion = | |
111 | kdb_get_master_key(master_key, master_key_schedule, NULL); | |
112 | ||
113 | ||
114 | if(mkeyversion < 0) { | |
115 | syslog(LOG_NOTICE, "couldn't verify master key"); | |
116 | cleanup(); | |
117 | exit(1); | |
118 | } | |
119 | ||
120 | /* get principal info */ | |
121 | rval = kerb_get_principal( | |
122 | kdata.pname, | |
123 | kdata.pinst, | |
124 | &principal_data, | |
125 | 1, | |
126 | &more | |
127 | ); | |
128 | ||
129 | if(rval != 1 || (more != 0)) { | |
130 | syslog(LOG_NOTICE, "more than 1 entry for %s.%s", | |
131 | kdata.pname, kdata.pinst); | |
132 | cleanup(); | |
133 | exit(1); | |
134 | } | |
135 | ||
136 | /* get the user's key */ | |
137 | ||
138 | bcopy(&principal_data.key_low, key, 4); | |
139 | bcopy(&principal_data.key_high, ((long *) key) + 1, 4); | |
140 | kdb_encrypt_key(key, key, master_key, master_key_schedule, | |
141 | DECRYPT); | |
142 | key_sched(key, key_schedule); | |
143 | des_set_key(key, key_schedule); | |
144 | ||
145 | ||
146 | /* get random key and send it over {random} Kperson */ | |
147 | ||
148 | random_key(kpwd_data.random_key); | |
149 | strcpy(kpwd_data.secure_msg, SECURE_STRING); | |
150 | if(des_write(0, &kpwd_data, sizeof(kpwd_data)) != sizeof(kpwd_data)) { | |
151 | syslog(LOG_ERR, "error writing initial data"); | |
152 | cleanup(); | |
153 | exit(1); | |
154 | } | |
155 | ||
156 | bzero(key, sizeof(key)); | |
157 | bzero(key_schedule, sizeof(key_schedule)); | |
158 | ||
159 | /* now read update info: { info }Krandom */ | |
160 | ||
161 | key_sched(kpwd_data.random_key, random_sched); | |
162 | des_set_key(kpwd_data.random_key, random_sched); | |
163 | if(des_read(0, &ud_data, sizeof(ud_data)) != sizeof(ud_data)) { | |
164 | syslog(LOG_ERR, "update aborted"); | |
165 | cleanup(); | |
166 | exit(1); | |
167 | } | |
168 | ||
169 | /* validate info string by looking at the embedded string */ | |
170 | ||
171 | if(strcmp(ud_data.secure_msg, SECURE_STRING)) { | |
172 | syslog(LOG_NOTICE, "invalid update from %s", | |
173 | inet_ntoa(foreign.sin_addr)); | |
174 | cleanup(); | |
175 | exit(1); | |
176 | } | |
177 | ||
178 | /* produce the new key entry in the database { key }Kmaster */ | |
179 | string_to_key(ud_data.pw, key); | |
180 | kdb_encrypt_key(key, key, | |
181 | master_key, master_key_schedule, | |
182 | ENCRYPT); | |
183 | bcopy(key, &principal_data.key_low, 4); | |
184 | bcopy(((long *) key) + 1, | |
185 | &principal_data.key_high, 4); | |
186 | bzero(key, sizeof(key)); | |
187 | principal_data.key_version++; | |
188 | if(kerb_put_principal(&principal_data, 1)) { | |
189 | syslog(LOG_ERR, "couldn't write new record for %s.%s", | |
190 | principal_data.name, principal_data.instance); | |
191 | cleanup(); | |
192 | exit(1); | |
193 | } | |
194 | ||
195 | syslog(LOG_NOTICE,"wrote new password field for %s.%s from %s", | |
196 | principal_data.name, | |
197 | principal_data.instance, | |
198 | inet_ntoa(foreign.sin_addr) | |
199 | ); | |
200 | ||
201 | send_ack(0, "Update complete.\n"); | |
202 | cleanup(); | |
203 | exit(0); | |
204 | } | |
205 | ||
206 | cleanup() | |
207 | { | |
208 | bzero(&kpwd_data, sizeof(kpwd_data)); | |
209 | bzero(master_key, sizeof(master_key)); | |
210 | bzero(master_key_schedule, sizeof(master_key_schedule)); | |
211 | bzero(key, sizeof(key)); | |
212 | bzero(key_schedule, sizeof(key_schedule)); | |
213 | bzero(random_sched, sizeof(random_sched)); | |
214 | bzero(&principal_data, sizeof(principal_data)); | |
215 | bzero(&ud_data, sizeof(ud_data)); | |
216 | } | |
217 | ||
218 | send_ack(remote, msg) | |
219 | int remote; | |
220 | char *msg; | |
221 | { | |
222 | int cc; | |
223 | cc = des_write(remote, msg, strlen(msg) + 1); | |
224 | if(cc <= 0) { | |
225 | syslog(LOG_ERR, "error writing ack"); | |
226 | cleanup(); | |
227 | exit(1); | |
228 | } | |
229 | } |