| 1 | |
| 2 | /* |
| 3 | ** Copyright 1998 - 2013 Double Precision, Inc. See COPYING for |
| 4 | ** distribution information. |
| 5 | */ |
| 6 | |
| 7 | #include "courier_auth_config.h" |
| 8 | #include "courierauthsasl.h" |
| 9 | #include "authsaslclient.h" |
| 10 | #include "cramlib.h" |
| 11 | #include <stdlib.h> |
| 12 | #include <ctype.h> |
| 13 | #include <string.h> |
| 14 | #include <errno.h> |
| 15 | |
| 16 | /* Use the SASL_LIST macro to build authsasl_list */ |
| 17 | |
| 18 | #define NO_SERVER_FUNC() |
| 19 | |
| 20 | #define SERVER_FUNC(b) int b(const char *, const char *, \ |
| 21 | char *(*)(const char *, void *), \ |
| 22 | void *, \ |
| 23 | char **, \ |
| 24 | char **); |
| 25 | |
| 26 | #define SASL(a,b,c) b |
| 27 | SASL_LIST |
| 28 | |
| 29 | #undef SASL |
| 30 | |
| 31 | #undef SERVER_FUNC |
| 32 | #define SERVER_FUNC(n) n |
| 33 | |
| 34 | #undef NO_SERVER_FUNC |
| 35 | #define NO_SERVER_FUNC() 0 |
| 36 | |
| 37 | #define SASL(a,b,c) {a, b}, |
| 38 | |
| 39 | struct authsasl_info authsasl_list[] = { |
| 40 | |
| 41 | SASL_LIST |
| 42 | |
| 43 | { 0, 0}}; |
| 44 | |
| 45 | int auth_sasl(const char *method, |
| 46 | const char *initreply, |
| 47 | char *(*callback_func)(const char *, void *), |
| 48 | void *callback_arg, |
| 49 | char **authtype_ptr, /* Returned - AUTHTYPE */ |
| 50 | char **authdata_ptr) |
| 51 | { |
| 52 | int i; |
| 53 | char *p, *q; |
| 54 | |
| 55 | if ((p=malloc(strlen(method)+1)) == 0) |
| 56 | return (0); |
| 57 | strcpy(p, method); |
| 58 | for (q=p; *q; q++) |
| 59 | *q=toupper((int)(unsigned char)*q); |
| 60 | |
| 61 | for (i=0; authsasl_list[i].sasl_method; i++) |
| 62 | { |
| 63 | if (strcmp(p, authsasl_list[i].sasl_method) == 0 && |
| 64 | authsasl_list[i].sasl_func) |
| 65 | { |
| 66 | free(p); |
| 67 | return ( (*authsasl_list[i].sasl_func) |
| 68 | (method, |
| 69 | initreply, callback_func, |
| 70 | callback_arg, |
| 71 | authtype_ptr, authdata_ptr)); |
| 72 | } |
| 73 | } |
| 74 | free(p); |
| 75 | errno=ENOENT; |
| 76 | return (AUTHSASL_ERROR); |
| 77 | } |
| 78 | |
| 79 | int auth_sasl_ex(const char *method, |
| 80 | const char *initresponse, |
| 81 | const char *externalauth, |
| 82 | char *(*callback_func)(const char *, void *), |
| 83 | void *callback_arg, |
| 84 | char **authtype_ptr, /* Returned - AUTHTYPE */ |
| 85 | char **authdata_ptr) |
| 86 | { |
| 87 | char *uid; |
| 88 | int n; |
| 89 | |
| 90 | if (strcmp(method, "EXTERNAL")) |
| 91 | return auth_sasl(method, initresponse, callback_func, |
| 92 | callback_arg, |
| 93 | authtype_ptr, |
| 94 | authdata_ptr); |
| 95 | |
| 96 | if (!externalauth || !*externalauth) |
| 97 | return AUTHSASL_ERROR; |
| 98 | |
| 99 | if (initresponse && !*initresponse) |
| 100 | initresponse=NULL; |
| 101 | |
| 102 | if (initresponse && strcmp(initresponse, externalauth)) |
| 103 | return AUTHSASL_ERROR; |
| 104 | |
| 105 | if (!initresponse) |
| 106 | { |
| 107 | uid=callback_func("", callback_arg); |
| 108 | |
| 109 | if (*uid == '*') |
| 110 | { |
| 111 | free(uid); |
| 112 | return (AUTHSASL_ABORTED); |
| 113 | } |
| 114 | |
| 115 | n=authsasl_frombase64(uid); |
| 116 | |
| 117 | if (n < 0) |
| 118 | { |
| 119 | free(uid); |
| 120 | return AUTHSASL_ABORTED; |
| 121 | } |
| 122 | uid[n]=0; |
| 123 | |
| 124 | if (uid[0]) |
| 125 | { |
| 126 | free(uid); |
| 127 | return AUTHSASL_ABORTED; |
| 128 | } |
| 129 | free(uid); |
| 130 | } |
| 131 | |
| 132 | if ((*authtype_ptr=strdup("EXTERNAL")) == NULL) |
| 133 | return AUTHSASL_ABORTED; |
| 134 | |
| 135 | if ((*authdata_ptr=strdup(externalauth)) == NULL) |
| 136 | { |
| 137 | free(authtype_ptr); |
| 138 | return AUTHSASL_ABORTED; |
| 139 | } |
| 140 | |
| 141 | return 0; |
| 142 | } |
| 143 | |
| 144 | char *auth_sasl_extract_userid(const char *authtype, |
| 145 | const char *authdata) |
| 146 | { |
| 147 | struct cram_callback_info cci; |
| 148 | char *p; |
| 149 | char *t; |
| 150 | char *d; |
| 151 | |
| 152 | if (strcmp(authtype, AUTHTYPE_LOGIN) == 0) |
| 153 | { |
| 154 | char *q; |
| 155 | |
| 156 | p=strdup(authdata); |
| 157 | |
| 158 | if (!p) |
| 159 | return NULL; |
| 160 | |
| 161 | q=strchr(p, '\n'); |
| 162 | if (q) *q=0; |
| 163 | return p; |
| 164 | } |
| 165 | |
| 166 | if ((t=strdup(authtype)) == NULL) |
| 167 | return NULL; |
| 168 | |
| 169 | if ((d=strdup(authdata)) == NULL) |
| 170 | { |
| 171 | free(t); |
| 172 | return NULL; |
| 173 | } |
| 174 | |
| 175 | if (auth_get_cram_silent(t, d, &cci)) |
| 176 | { |
| 177 | free(d); |
| 178 | free(t); |
| 179 | return (NULL); |
| 180 | } |
| 181 | |
| 182 | p=strdup(cci.user); |
| 183 | free(d); |
| 184 | free(t); |
| 185 | return p; |
| 186 | } |