etc/services - sync with NetBSD-8
[minix.git] / crypto / external / bsd / heimdal / dist / lib / ntlm / apop.c
blobf8446a011c76dd71209647349c8d573a6940ab3a
1 /* $NetBSD: apop.c,v 1.1.1.2 2014/04/24 12:45:51 pettai Exp $ */
3 /*
4 * Copyright (c) 2010 Kungliga Tekniska Högskolan
5 * (Royal Institute of Technology, Stockholm, Sweden).
6 * All rights reserved.
8 * Portions Copyright (c) 2010 Apple Inc. All rights reserved.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
21 * 3. Neither the name of the Institute nor the names of its contributors
22 * may be used to endorse or promote products derived from this software
23 * without specific prior written permission.
25 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SUCH DAMAGE.
38 #include <sys/types.h>
39 #include <stdio.h>
40 #include <unistd.h>
41 #include <CommonCrypto/CommonDigest.h>
42 #include <CommonCrypto/CommonHMAC.h>
43 #include <krb5/roken.h>
44 #include <krb5/hex.h>
45 #include "heim-auth.h"
46 #include <krb5/ntlm_err.h>
48 char *
49 heim_generate_challenge(const char *hostname)
51 char host[MAXHOSTNAMELEN], *str = NULL;
52 uint32_t num, t;
54 if (hostname == NULL) {
55 if (gethostname(host, sizeof(host)))
56 return NULL;
57 hostname = host;
60 t = time(NULL);
61 num = rk_random();
63 asprintf(&str, "<%lu%lu@%s>", (unsigned long)t,
64 (unsigned long)num, hostname);
66 return str;
69 char *
70 heim_apop_create(const char *challenge, const char *password)
72 char *str = NULL;
73 uint8_t hash[CC_MD5_DIGEST_LENGTH];
74 CC_MD5_CTX ctx;
76 CC_MD5_Init(&ctx);
77 CC_MD5_Update(&ctx, challenge, strlen(challenge));
78 CC_MD5_Update(&ctx, password, strlen(password));
80 CC_MD5_Final(hash, &ctx);
82 hex_encode(hash, sizeof(hash), &str);
83 if (str)
84 strlwr(str);
86 return str;
89 int
90 heim_apop_verify(const char *challenge, const char *password, const char *response)
92 char *str;
93 int res;
95 str = heim_apop_create(challenge, password);
96 if (str == NULL)
97 return ENOMEM;
99 res = (strcasecmp(str, response) != 0);
100 free(str);
102 if (res)
103 return HNTLM_ERR_INVALID_APOP;
104 return 0;
107 struct heim_cram_md5 {
108 CC_MD5_CTX ipad;
109 CC_MD5_CTX opad;
113 void
114 heim_cram_md5_export(const char *password, heim_CRAM_MD5_STATE *state)
116 size_t keylen = strlen(password);
117 uint8_t key[CC_MD5_BLOCK_BYTES];
118 uint8_t pad[CC_MD5_BLOCK_BYTES];
119 struct heim_cram_md5 ctx;
120 size_t n;
122 memset(&ctx, 0, sizeof(ctx));
124 if (keylen > CC_MD5_BLOCK_BYTES) {
125 CC_MD5(password, keylen, key);
126 keylen = sizeof(keylen);
127 } else {
128 memcpy(key, password, keylen);
131 memset(pad, 0x36, sizeof(pad));
132 for (n = 0; n < keylen; n++)
133 pad[n] ^= key[n];
135 CC_MD5_Init(&ctx.ipad);
136 CC_MD5_Init(&ctx.opad);
138 CC_MD5_Update(&ctx.ipad, pad, sizeof(pad));
140 memset(pad, 0x5c, sizeof(pad));
141 for (n = 0; n < keylen; n++)
142 pad[n] ^= key[n];
144 CC_MD5_Update(&ctx.opad, pad, sizeof(pad));
146 memset(pad, 0, sizeof(pad));
147 memset(key, 0, sizeof(key));
149 state->istate[0] = htonl(ctx.ipad.A);
150 state->istate[1] = htonl(ctx.ipad.B);
151 state->istate[2] = htonl(ctx.ipad.C);
152 state->istate[3] = htonl(ctx.ipad.D);
154 state->ostate[0] = htonl(ctx.opad.A);
155 state->ostate[1] = htonl(ctx.opad.B);
156 state->ostate[2] = htonl(ctx.opad.C);
157 state->ostate[3] = htonl(ctx.opad.D);
159 memset(&ctx, 0, sizeof(ctx));
163 heim_cram_md5
164 heim_cram_md5_import(void *data, size_t len)
166 heim_CRAM_MD5_STATE state;
167 heim_cram_md5 ctx;
168 unsigned n;
170 if (len != sizeof(state))
171 return NULL;
173 ctx = calloc(1, sizeof(*ctx));
174 if (ctx == NULL)
175 return NULL;
177 memcpy(&state, data, sizeof(state));
179 ctx->ipad.A = ntohl(state.istate[0]);
180 ctx->ipad.B = ntohl(state.istate[1]);
181 ctx->ipad.C = ntohl(state.istate[2]);
182 ctx->ipad.D = ntohl(state.istate[3]);
184 ctx->opad.A = ntohl(state.ostate[0]);
185 ctx->opad.B = ntohl(state.ostate[1]);
186 ctx->opad.C = ntohl(state.ostate[2]);
187 ctx->opad.D = ntohl(state.ostate[3]);
189 ctx->ipad.Nl = ctx->opad.Nl = 512;
190 ctx->ipad.Nh = ctx->opad.Nh = 0;
191 ctx->ipad.num = ctx->opad.num = 0;
193 return ctx;
197 heim_cram_md5_verify_ctx(heim_cram_md5 ctx, const char *challenge, const char *response)
199 uint8_t hash[CC_MD5_DIGEST_LENGTH];
200 char *str = NULL;
201 int res;
203 CC_MD5_Update(&ctx->ipad, challenge, strlen(challenge));
204 CC_MD5_Final(hash, &ctx->ipad);
206 CC_MD5_Update(&ctx->opad, hash, sizeof(hash));
207 CC_MD5_Final(hash, &ctx->opad);
209 hex_encode(hash, sizeof(hash), &str);
210 if (str == NULL)
211 return ENOMEM;
213 res = (strcasecmp(str, response) != 0);
214 free(str);
216 if (res)
217 return HNTLM_ERR_INVALID_CRAM_MD5;
218 return 0;
221 void
222 heim_cram_md5_free(heim_cram_md5 ctx)
224 memset(ctx, 0, sizeof(*ctx));
225 free(ctx);
229 char *
230 heim_cram_md5_create(const char *challenge, const char *password)
232 CCHmacContext ctx;
233 uint8_t hash[CC_MD5_DIGEST_LENGTH];
234 char *str = NULL;
236 CCHmacInit(&ctx, kCCHmacAlgMD5, password, strlen(password));
237 CCHmacUpdate(&ctx, challenge, strlen(challenge));
238 CCHmacFinal(&ctx, hash);
240 memset(&ctx, 0, sizeof(ctx));
242 hex_encode(hash, sizeof(hash), &str);
243 if (str)
244 strlwr(str);
246 return str;
250 heim_cram_md5_verify(const char *challenge, const char *password, const char *response)
252 char *str;
253 int res;
255 str = heim_cram_md5_create(challenge, password);
256 if (str == NULL)
257 return ENOMEM;
259 res = (strcasecmp(str, response) != 0);
260 free(str);
262 if (res)
263 return HNTLM_ERR_INVALID_CRAM_MD5;
264 return 0;