1 /* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
6 #include <sasl/saslplug.h>
8 char my_sasl_hostname
[1025];
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
14 const char * const locations
[] = {
15 "/etc/sasl/memcached.conf",
16 "/etc/sasl2/memcached.conf",
21 #ifndef HAVE_SASL_CALLBACK_FT
22 typedef int (*sasl_callback_ft
)(void);
25 #ifdef ENABLE_SASL_PWDB
26 #define MAX_ENTRY_LEN 256
28 static const char *memcached_sasl_pwdb
;
30 static int sasl_server_userdb_checkpass(sasl_conn_t
*conn
,
35 struct propctx
*propctx
)
37 size_t unmlen
= strlen(user
);
38 if ((passlen
+ unmlen
) > (MAX_ENTRY_LEN
- 4)) {
40 "WARNING: Failed to authenticate <%s> due to too long password (%d)\n",
45 FILE *pwfile
= fopen(memcached_sasl_pwdb
, "r");
47 if (settings
.verbose
) {
48 vperror("WARNING: Failed to open sasl database <%s>",
54 char buffer
[MAX_ENTRY_LEN
];
57 while ((fgets(buffer
, sizeof(buffer
), pwfile
)) != NULL
) {
58 if (memcmp(user
, buffer
, unmlen
) == 0 && buffer
[unmlen
] == ':') {
59 /* This is the correct user */
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 */
77 if (settings
.verbose
) {
78 fprintf(stderr
, "INFO: User <%s> failed to authenticate\n", user
);
85 #ifdef HAVE_SASL_CB_GETCONF
86 static int sasl_getconf(void *context
, const char **path
)
88 *path
= getenv("SASL_CONF_PATH");
91 for (int i
= 0; locations
[i
] != NULL
; ++i
) {
92 if (access(locations
[i
], F_OK
) == 0) {
99 if (settings
.verbose
) {
101 fprintf(stderr
, "Reading configuration from: <%s>\n", *path
);
103 fprintf(stderr
, "Failed to locate a config path\n");
108 return (*path
!= NULL
) ? SASL_OK
: SASL_FAIL
;
112 static int sasl_log(void *context
, int level
, const char *message
)
124 if (settings
.verbose
< 2) {
130 if (settings
.verbose
< 1) {
135 /* This is an error */
140 fprintf(stderr
, "SASL (severity %d): %s\n", level
, message
);
146 static sasl_callback_t sasl_callbacks
[] = {
147 #ifdef ENABLE_SASL_PWDB
148 { SASL_CB_SERVER_USERDB_CHECKPASS
, sasl_server_userdb_checkpass
, NULL
},
151 { SASL_CB_LOG
, (sasl_callback_ft
)sasl_log
, NULL
},
153 #ifdef HAVE_SASL_CB_GETCONF
154 { SASL_CB_GETCONF
, sasl_getconf
, NULL
},
157 { SASL_CB_LIST_END
, NULL
, NULL
}
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
) {
166 "INFO: MEMCACHED_SASL_PWDB not specified. "
167 "Internal passwd database disabled\n");
169 sasl_callbacks
[0].id
= SASL_CB_LIST_END
;
170 sasl_callbacks
[0].proc
= NULL
;
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");
179 my_sasl_hostname
[0] = '\0';
182 if (sasl_server_init(sasl_callbacks
, "memcached") != SASL_OK
) {
183 fprintf(stderr
, "Error initializing sasl.\n");
186 if (settings
.verbose
) {
187 fprintf(stderr
, "Initialized SASL.\n");