Update hardening rules.
[awesomized/libmemcached] / memcached / sasl_defs.c
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>
6 #include <sasl/saslplug.h>
7
8 char my_sasl_hostname[1025];
9
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
21 #ifndef HAVE_SASL_CALLBACK_FT
22 typedef int (*sasl_callback_ft)(void);
23 #endif
24
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
151 { SASL_CB_LOG, (sasl_callback_ft)sasl_log, NULL },
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
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
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 }