Import Upstream version 0.66.4
[hcoop/debian/courier-authlib.git] / authsaslcram.c
CommitLineData
d9898ee8 1
2/*
3** Copyright 1998 - 2006 Double Precision, Inc. See COPYING for
4** distribution information.
5*/
6
7#include "courier_auth_config.h"
8#include "random128/random128.h"
9#include "courierauthsasl.h"
10#include <stdlib.h>
11#include <string.h>
12#if HAVE_UNISTD_H
13#include <unistd.h>
14#endif
15#include <ctype.h>
16#include <stdio.h>
17#include <errno.h>
18
19extern char *strdupdefdomain(const char *userid, const char *s1,
20 const char *s2, const char *s3);
21
22int authsasl_cram(const char *method, const char *initresponse,
23 char *(*getresp)(const char *, void *),
24 void *callback_arg,
25 char **authtype,
26 char **authdata)
27{
28const char *randtoken;
29char hostnamebuf[256];
30char *challenge;
31char *challenge_base64;
32char *response;
33char *chrsp;
34char *q, *r, *s, *t;
35int plen;
36
37 if (initresponse && *initresponse)
38 {
39 if (write(2, "authsasl_cram: invalid request.\n", 32) < 0)
40 ; /* ignore gcc warning */
41 return (AUTHSASL_ERROR);
42 }
43
44 randtoken=random128();
45 hostnamebuf[0]=0;
46 if (gethostname(hostnamebuf, sizeof(hostnamebuf)-1))
47 strcpy(hostnamebuf, "cram");
48
49 challenge=malloc(strlen(randtoken)+strlen(hostnamebuf)
50 +sizeof("<@>"));
51 if (!challenge)
52 {
53 perror("malloc");
54 return (AUTHSASL_ERROR);
55 }
56 strcat(strcat(strcat(strcat(strcpy(challenge, "<"),
57 randtoken), "@"), hostnamebuf), ">");
58
59 challenge_base64=authsasl_tobase64(challenge, -1);
60 free(challenge);
61 if (!challenge_base64)
62 {
63 perror("malloc");
64 return (AUTHSASL_ERROR);
65 }
66
67 response=getresp(challenge_base64, callback_arg);
68 if (!response)
69 {
70 free(challenge_base64);
71 return (AUTHSASL_ERROR);
72 }
73
74 if (*response == '*')
75 {
76 free(challenge_base64);
77 free(response);
78 return (AUTHSASL_ABORTED);
79 }
80
81 /* If DEFDOMAIN is set, pick apart the response and reassemble
82 * it, potentially with a default domain appended to the username */
83 q=getenv("DEFDOMAIN");
84 if (q && q[0])
85 {
86 r = 0;
87 if ( (plen = authsasl_frombase64(response)) > 0 &&
88 (response[plen]=0, (s = strchr(response, ' ')) != 0) &&
89 (*s++ = 0, (t = strdupdefdomain(response, " ", s, "")) != 0) )
90 {
91 r = authsasl_tobase64(t, -1);
92 free(t);
93 }
94 free(response);
95 if ((response = r) == 0)
96 {
97 free(challenge_base64);
98 return (AUTHSASL_ERROR);
99 }
100 }
101
102 chrsp=malloc(strlen(challenge_base64)+strlen(response)+3);
103 if (!chrsp)
104 {
105 free(challenge_base64);
106 free(response);
107 perror("malloc");
108 return (AUTHSASL_ERROR);
109 }
110
111 strcat(strcat(strcat(strcpy(chrsp, challenge_base64), "\n"),
112 response), "\n");
113 free(challenge_base64);
114 free(response);
115
116 if ( (*authtype=malloc(strlen(method)+1)) == 0)
117 {
118 free(chrsp);
119 perror("malloc");
120 return (AUTHSASL_ERROR);
121 }
122 strcpy( *authtype, method );
123 *authdata=chrsp;
124
125 for (chrsp= *authtype; *chrsp; chrsp++)
126 *chrsp= tolower( (int)(unsigned char)*chrsp );
127
128 return (AUTHSASL_OK);
129}