No empty .Rs/.Re
[netbsd-mini2440.git] / crypto / dist / heimdal / appl / popper / auth_krb4.c
blob0829684ae55158f7ebea9a1c81cf23dcdd7d0e64
1 /*
2 * Copyright (c) 2004 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
34 #include <popper.h>
35 #include <base64.h>
36 #include <pop_auth.h>
37 __RCSID("$Heimdal: auth_krb4.c 17450 2006-05-05 11:11:43Z lha $"
38 "$NetBSD$");
41 #if defined(SASL) && defined(KRB4)
42 #include <krb.h>
43 #include <des.h>
45 struct krb4_state {
46 int stage;
47 uint32_t nonce;
50 static int
51 krb4_loop(POP *p, void *state,
52 /* const */ void *input, size_t input_length,
53 void **output, size_t *output_length)
55 struct krb4_state *ks = state;
57 int ret;
58 des_cblock key;
59 unsigned char *data;
60 char instance[INST_SZ];
61 des_key_schedule schedule;
63 if(ks->stage == 0) {
64 if(input_length > 0)
65 return POP_AUTH_FAILURE;
66 /* S -> C: 32 bit nonce in MSB base64 */
67 #ifdef HAVE_OPENSSL
68 #define des_new_random_key des_random_key
69 #endif
70 des_new_random_key(key);
71 ks->nonce = (key[0] | (key[1] << 8) | (key[2] << 16) | (key[3] << 24)
72 | key[4] | (key[5] << 8) | (key[6] << 16) | (key[7] << 24));
73 *output = malloc(4);
74 if(*output == NULL) {
75 pop_auth_set_error("out of memory");
76 return POP_AUTH_FAILURE;
78 krb_put_int(ks->nonce, *output, 4, 4);
79 *output_length = 4;
80 ks->stage++;
81 return POP_AUTH_CONTINUE;
84 if(ks->stage == 1) {
85 KTEXT_ST authent;
86 /* C -> S: ticket and authenticator */
88 if (input_length > sizeof(authent.dat)) {
89 pop_auth_set_error("data packet too long");
90 return POP_AUTH_FAILURE;
92 memcpy(authent.dat, input, input_length);
93 authent.length = input_length;
95 k_getsockinst (0, instance, sizeof(instance));
96 ret = krb_rd_req(&authent, "pop", instance,
97 0 /* XXX p->in_addr.sin_addr.s_addr */,
98 &p->kdata, NULL);
99 if (ret != 0) {
100 pop_auth_set_error(krb_get_err_text(ret));
101 return POP_AUTH_FAILURE;
103 if (p->kdata.checksum != ks->nonce) {
104 pop_auth_set_error("data stream modified");
105 return POP_AUTH_FAILURE;
107 /* S -> C: nonce + 1 | bit | max segment */
109 *output = malloc(8);
110 if(*output == NULL) {
111 pop_auth_set_error("out of memory");
112 return POP_AUTH_FAILURE;
114 data = *output;
115 krb_put_int(ks->nonce + 1, data, 8, 4);
116 data[4] = 1;
117 data[5] = 0;
118 data[6] = 0;
119 data[7] = 0;
120 des_key_sched(&p->kdata.session, schedule);
121 des_pcbc_encrypt((des_cblock*)data,
122 (des_cblock*)data, 8,
123 schedule,
124 &p->kdata.session,
125 DES_ENCRYPT);
126 *output_length = 8;
127 ks->stage++;
128 return POP_AUTH_CONTINUE;
131 if(ks->stage == 2) {
132 uint32_t nonce_reply;
133 /* C -> S: nonce | bit | max segment | username */
135 if (input_length % 8 != 0) {
136 pop_auth_set_error("reply is not a multiple of 8 bytes");
137 return POP_AUTH_FAILURE;
140 des_key_sched(&p->kdata.session, schedule);
141 des_pcbc_encrypt((des_cblock*)input,
142 (des_cblock*)input,
143 input_length,
144 schedule,
145 &p->kdata.session,
146 DES_DECRYPT);
148 data = input;
149 krb_get_int(data, &nonce_reply, 4, 0);
150 if (nonce_reply != ks->nonce) {
151 pop_auth_set_error("data stream modified");
152 return POP_AUTH_FAILURE;
154 if(data[4] != 1) {
157 if(data[input_length - 1] != '\0') {
158 pop_auth_set_error("bad format of username");
159 return POP_AUTH_FAILURE;
161 strlcpy(p->user, data + 8, sizeof(p->user));
162 if (kuserok(&p->kdata, p->user)) {
163 pop_log(p, POP_PRIORITY,
164 "%s: (%s.%s@%s) tried to retrieve mail for %s.",
165 p->client, p->kdata.pname, p->kdata.pinst,
166 p->kdata.prealm, p->user);
167 pop_auth_set_error("Permission denied");
168 return POP_AUTH_FAILURE;
170 pop_log(p, POP_INFO, "%s: %s.%s@%s -> %s",
171 p->ipaddr,
172 p->kdata.pname, p->kdata.pinst, p->kdata.prealm,
173 p->user);
174 return POP_AUTH_COMPLETE;
176 return POP_AUTH_FAILURE;
180 static int
181 krb4_init(POP *p, void **state)
183 struct krb4_state *ks = malloc(sizeof(*ks));
184 if(ks == NULL) {
185 pop_auth_set_error("out of memory");
186 return POP_AUTH_FAILURE;
188 ks->stage = 0;
189 *state = ks;
190 return POP_AUTH_CONTINUE;
193 static int
194 krb4_cleanup(POP *p, void *state)
196 free(state);
197 return POP_AUTH_CONTINUE;
200 struct auth_mech krb4_mech = {
201 "KERBEROS_V4", krb4_init, krb4_loop, krb4_cleanup
204 #endif /* KRB5 */