2 * Copyright (c) 2004 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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
37 __RCSID("$Heimdal: auth_krb4.c 17450 2006-05-05 11:11:43Z lha $"
41 #if defined(SASL) && defined(KRB4)
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
;
60 char instance
[INST_SZ
];
61 des_key_schedule schedule
;
65 return POP_AUTH_FAILURE
;
66 /* S -> C: 32 bit nonce in MSB base64 */
68 #define des_new_random_key des_random_key
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));
75 pop_auth_set_error("out of memory");
76 return POP_AUTH_FAILURE
;
78 krb_put_int(ks
->nonce
, *output
, 4, 4);
81 return POP_AUTH_CONTINUE
;
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 */,
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 */
110 if(*output
== NULL
) {
111 pop_auth_set_error("out of memory");
112 return POP_AUTH_FAILURE
;
115 krb_put_int(ks
->nonce
+ 1, data
, 8, 4);
120 des_key_sched(&p
->kdata
.session
, schedule
);
121 des_pcbc_encrypt((des_cblock
*)data
,
122 (des_cblock
*)data
, 8,
128 return POP_AUTH_CONTINUE
;
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
,
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
;
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",
172 p
->kdata
.pname
, p
->kdata
.pinst
, p
->kdata
.prealm
,
174 return POP_AUTH_COMPLETE
;
176 return POP_AUTH_FAILURE
;
181 krb4_init(POP
*p
, void **state
)
183 struct krb4_state
*ks
= malloc(sizeof(*ks
));
185 pop_auth_set_error("out of memory");
186 return POP_AUTH_FAILURE
;
190 return POP_AUTH_CONTINUE
;
194 krb4_cleanup(POP
*p
, void *state
)
197 return POP_AUTH_CONTINUE
;
200 struct auth_mech krb4_mech
= {
201 "KERBEROS_V4", krb4_init
, krb4_loop
, krb4_cleanup