1.4.3
by David Martínez Moreno
Import upstream version 1.4.5 |
1 |
/* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
|
2 |
#include "memcached.h" |
|
3 |
#include <stdio.h> |
|
4 |
#include <stdlib.h> |
|
5 |
#include <string.h> |
|
1.1.11
by Scott Kitterman
Import upstream version 1.4.11 |
6 |
#include <sasl/saslplug.h> |
3.3.5
by Arno Töll
* Non-maintainer upload. |
7 |
|
1.1.12
by Clint Byrum
Import upstream version 1.4.13 |
8 |
char my_sasl_hostname[1025]; |
9 |
||
1.4.3
by David Martínez Moreno
Import upstream version 1.4.5 |
10 |
#ifdef HAVE_SASL_CB_GETCONF
|
11 |
/* The locations we may search for a SASL config file if the user didn't
|
|
12 |
* specify one in the environment variable SASL_CONF_PATH
|
|
13 |
*/
|
|
14 |
const char * const locations[] = { |
|
15 |
"/etc/sasl/memcached.conf", |
|
16 |
"/etc/sasl2/memcached.conf", |
|
17 |
NULL
|
|
18 |
};
|
|
19 |
#endif
|
|
20 |
||
1.1.12
by Clint Byrum
Import upstream version 1.4.13 |
21 |
#ifndef HAVE_SASL_CALLBACK_FT
|
22 |
typedef int (*sasl_callback_ft)(void); |
|
23 |
#endif
|
|
24 |
||
1.4.3
by David Martínez Moreno
Import upstream version 1.4.5 |
25 |
#ifdef ENABLE_SASL_PWDB
|
26 |
#define MAX_ENTRY_LEN 256
|
|
27 |
||
28 |
static const char *memcached_sasl_pwdb; |
|
29 |
||
30 |
static int sasl_server_userdb_checkpass(sasl_conn_t *conn, |
|
31 |
void *context, |
|
32 |
const char *user, |
|
33 |
const char *pass, |
|
34 |
unsigned passlen, |
|
35 |
struct propctx *propctx) |
|
36 |
{
|
|
37 |
size_t unmlen = strlen(user); |
|
38 |
if ((passlen + unmlen) > (MAX_ENTRY_LEN - 4)) { |
|
39 |
fprintf(stderr, |
|
40 |
"WARNING: Failed to authenticate <%s> due to too long password (%d)\n", |
|
41 |
user, passlen); |
|
42 |
return SASL_NOAUTHZ; |
|
43 |
}
|
|
44 |
||
45 |
FILE *pwfile = fopen(memcached_sasl_pwdb, "r"); |
|
46 |
if (pwfile == NULL) { |
|
47 |
if (settings.verbose) { |
|
48 |
vperror("WARNING: Failed to open sasl database <%s>", |
|
49 |
memcached_sasl_pwdb); |
|
50 |
}
|
|
51 |
return SASL_NOAUTHZ; |
|
52 |
}
|
|
53 |
||
54 |
char buffer[MAX_ENTRY_LEN]; |
|
55 |
bool ok = false; |
|
56 |
||
57 |
while ((fgets(buffer, sizeof(buffer), pwfile)) != NULL) { |
|
58 |
if (memcmp(user, buffer, unmlen) == 0 && buffer[unmlen] == ':') { |
|
59 |
/* This is the correct user */
|
|
60 |
++unmlen; |
|
61 |
if (memcmp(pass, buffer + unmlen, passlen) == 0 && |
|
62 |
(buffer[unmlen + passlen] == ':' || /* Additional tokens */ |
|
63 |
buffer[unmlen + passlen] == '\n' || /* end of line */ |
|
64 |
buffer[unmlen + passlen] == '\r'|| /* dos format? */ |
|
65 |
buffer[unmlen + passlen] == '\0')) { /* line truncated */ |
|
66 |
ok = true; |
|
67 |
}
|
|
68 |
||
69 |
break; |
|
70 |
}
|
|
71 |
}
|
|
72 |
(void)fclose(pwfile); |
|
73 |
if (ok) { |
|
74 |
return SASL_OK; |
|
75 |
}
|
|
76 |
||
77 |
if (settings.verbose) { |
|
78 |
fprintf(stderr, "INFO: User <%s> failed to authenticate\n", user); |
|
79 |
}
|
|
80 |
||
81 |
return SASL_NOAUTHZ; |
|
82 |
}
|
|
83 |
#endif
|
|
84 |
||
85 |
#ifdef HAVE_SASL_CB_GETCONF
|
|
86 |
static int sasl_getconf(void *context, const char **path) |
|
87 |
{
|
|
88 |
*path = getenv("SASL_CONF_PATH"); |
|
89 |
||
90 |
if (*path == NULL) { |
|
91 |
for (int i = 0; locations[i] != NULL; ++i) { |
|
92 |
if (access(locations[i], F_OK) == 0) { |
|
93 |
*path = locations[i]; |
|
94 |
break; |
|
95 |
}
|
|
96 |
}
|
|
97 |
}
|
|
98 |
||
99 |
if (settings.verbose) { |
|
100 |
if (*path != NULL) { |
|
101 |
fprintf(stderr, "Reading configuration from: <%s>\n", *path); |
|
102 |
} else { |
|
103 |
fprintf(stderr, "Failed to locate a config path\n"); |
|
104 |
}
|
|
105 |
||
106 |
}
|
|
107 |
||
108 |
return (*path != NULL) ? SASL_OK : SASL_FAIL; |
|
109 |
}
|
|
110 |
#endif
|
|
111 |
||
112 |
static int sasl_log(void *context, int level, const char *message) |
|
113 |
{
|
|
114 |
bool log = true; |
|
115 |
||
116 |
switch (level) { |
|
117 |
case SASL_LOG_NONE: |
|
118 |
log = false; |
|
119 |
break; |
|
120 |
case SASL_LOG_PASS: |
|
121 |
case SASL_LOG_TRACE: |
|
122 |
case SASL_LOG_DEBUG: |
|
123 |
case SASL_LOG_NOTE: |
|
124 |
if (settings.verbose < 2) { |
|
125 |
log = false; |
|
126 |
}
|
|
127 |
break; |
|
128 |
case SASL_LOG_WARN: |
|
129 |
case SASL_LOG_FAIL: |
|
130 |
if (settings.verbose < 1) { |
|
131 |
log = false; |
|
132 |
}
|
|
133 |
break; |
|
134 |
default: |
|
135 |
/* This is an error */
|
|
136 |
;
|
|
137 |
}
|
|
138 |
||
139 |
if (log) { |
|
140 |
fprintf(stderr, "SASL (severity %d): %s\n", level, message); |
|
141 |
}
|
|
142 |
||
143 |
return SASL_OK; |
|
144 |
}
|
|
145 |
||
146 |
static sasl_callback_t sasl_callbacks[] = { |
|
147 |
#ifdef ENABLE_SASL_PWDB
|
|
148 |
{ SASL_CB_SERVER_USERDB_CHECKPASS, sasl_server_userdb_checkpass, NULL }, |
|
149 |
#endif
|
|
150 |
||
1.1.11
by Scott Kitterman
Import upstream version 1.4.11 |
151 |
{ SASL_CB_LOG, (sasl_callback_ft)sasl_log, NULL }, |
1.4.3
by David Martínez Moreno
Import upstream version 1.4.5 |
152 |
|
153 |
#ifdef HAVE_SASL_CB_GETCONF
|
|
154 |
{ SASL_CB_GETCONF, sasl_getconf, NULL }, |
|
155 |
#endif
|
|
156 |
||
157 |
{ SASL_CB_LIST_END, NULL, NULL } |
|
158 |
};
|
|
159 |
||
160 |
void init_sasl(void) { |
|
161 |
#ifdef ENABLE_SASL_PWDB
|
|
162 |
memcached_sasl_pwdb = getenv("MEMCACHED_SASL_PWDB"); |
|
163 |
if (memcached_sasl_pwdb == NULL) { |
|
164 |
if (settings.verbose) { |
|
165 |
fprintf(stderr, |
|
166 |
"INFO: MEMCACHED_SASL_PWDB not specified. "
|
|
167 |
"Internal passwd database disabled\n"); |
|
168 |
}
|
|
169 |
sasl_callbacks[0].id = SASL_CB_LIST_END; |
|
170 |
sasl_callbacks[0].proc = NULL; |
|
171 |
}
|
|
172 |
#endif
|
|
173 |
||
1.1.12
by Clint Byrum
Import upstream version 1.4.13 |
174 |
memset(my_sasl_hostname, 0, sizeof(my_sasl_hostname)); |
175 |
if (gethostname(my_sasl_hostname, sizeof(my_sasl_hostname)-1) == -1) { |
|
176 |
if (settings.verbose) { |
|
177 |
fprintf(stderr, "Error discovering hostname for SASL\n"); |
|
178 |
}
|
|
179 |
my_sasl_hostname[0] = '\0'; |
|
180 |
}
|
|
181 |
||
1.4.3
by David Martínez Moreno
Import upstream version 1.4.5 |
182 |
if (sasl_server_init(sasl_callbacks, "memcached") != SASL_OK) { |
183 |
fprintf(stderr, "Error initializing sasl.\n"); |
|
184 |
exit(EXIT_FAILURE); |
|
185 |
} else { |
|
186 |
if (settings.verbose) { |
|
187 |
fprintf(stderr, "Initialized SASL.\n"); |
|
188 |
}
|
|
189 |
}
|
|
190 |
}
|