Merge lp:~dave-terei/libmemcached/libmemcached into lp:libmemcached

Proposed by David Terei
Status: Needs review
Proposed branch: lp:~dave-terei/libmemcached/libmemcached
Merge into: lp:libmemcached
Diff against target: 899 lines (+403/-345)
8 files modified
bootstrap.sh (+10/-1)
libmemcached-1.2/include.am (+1/-0)
libmemcached-1.2/isasl.h (+92/-0)
libmemcached-1.2/sasl.h (+1/-5)
libmemcached-1.2/struct/sasl.h (+2/-6)
libmemcached/include.am (+1/-0)
libmemcached/sasl.cc (+104/-333)
libmemcached/sasl_client.cc (+192/-0)
To merge this branch: bzr merge lp:~dave-terei/libmemcached/libmemcached
Reviewer Review Type Date Requested Status
Tangent Trunk Pending
Review via email: mp+224003@code.launchpad.net

Description of the change

Move to an internal SASL library taken from the membase guys. This removes the dependency on Cyrus SASL. It only supports PLAIN authentication, which seems fine as it's the only authentication mechanism other clients and memcached itself appears to support.

This enables SASL auth to be on by default which has great flow on effects for the community as right now most clients don't support SASL since they can't rely on libmemcached supporting it.

The removal of libsasl isn't complete (i.e., from configure scripts and build system) but I don't have a great grasp of that stuff. This is a initial step in the direction where the final stages of cleaning up should be trivial for someone who knows the code base.

To post a comment you must log in.
Revision history for this message
David Terei (dave-terei) wrote :

Any update on this?

Unmerged revisions

1115. By David Terei <email address hidden>

Move to internal (ISASL) library rather than cyrus SASL to enable SASL on by default.

ISASL library from membase.

1114. By David Terei <email address hidden>

Add support for Arch linux to build system.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'bootstrap.sh'
2--- bootstrap.sh 2014-02-16 11:31:04 +0000
3+++ bootstrap.sh 2014-06-20 23:47:25 +0000
4@@ -191,6 +191,9 @@
5 opensuse)
6 VENDOR_DISTRIBUTION='opensuse'
7 ;;
8+ arch)
9+ VENDOR_DISTRIBUTION='arch'
10+ ;;
11 *)
12 die "attempt to set an invalid VENDOR_DISTRIBUTION=$dist"
13 ;;
14@@ -262,6 +265,9 @@
15 opensuse)
16 VENDOR_RELEASE="$release"
17 ;;
18+ arch)
19+ VENDOR_RELEASE="$release"
20+ ;;
21 unknown)
22 die "attempt to set VENDOR_RELEASE without setting VENDOR_DISTRIBUTION"
23 ;;
24@@ -311,8 +317,11 @@
25 suse)
26 VENDOR='suse'
27 ;;
28+ arch)
29+ VENDOR='arch'
30+ ;;
31 *)
32- die "An attempt was made to set an invalid VENDOR=$_vendor"
33+ die "An attempt was made to set an invalid VENDOR=$vendor"
34 ;;
35 esac
36
37
38=== modified file 'libmemcached-1.2/include.am'
39--- libmemcached-1.2/include.am 2013-06-11 12:31:47 +0000
40+++ libmemcached-1.2/include.am 2014-06-20 23:47:25 +0000
41@@ -33,6 +33,7 @@
42 nobase_include_HEADERS+= libmemcached-1.2/flush_buffers.h
43 nobase_include_HEADERS+= libmemcached-1.2/get.h
44 nobase_include_HEADERS+= libmemcached-1.2/hash.h
45+nobase_include_HEADERS+= libmemcached-1.2/isasl.h
46 nobase_include_HEADERS+= libmemcached-1.2/limits.h
47 nobase_include_HEADERS+= libmemcached-1.2/memcached.h
48 nobase_include_HEADERS+= libmemcached-1.2/memcached.hpp
49
50=== added file 'libmemcached-1.2/isasl.h'
51--- libmemcached-1.2/isasl.h 1970-01-01 00:00:00 +0000
52+++ libmemcached-1.2/isasl.h 2014-06-20 23:47:25 +0000
53@@ -0,0 +1,92 @@
54+/* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
55+/*
56+ * Copyright (C) 2010 Membase, Inc
57+ * All rights reserved.
58+ *
59+ * Licensed under the Apache License, Version 2.0 (the "License");
60+ * you may not use this file except in compliance with the License.
61+ * You may obtain a copy of the License at
62+ *
63+ * http://www.apache.org/licenses/LICENSE-2.0
64+ *
65+ * Unless required by applicable law or agreed to in writing, software
66+ * distributed under the License is distributed on an "AS IS" BASIS,
67+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
68+ * See the License for the specific language governing permissions and
69+ * limitations under the License.
70+ */
71+
72+/* This is a minimalistic SASL implementation */
73+#ifndef SASL_ISASL_H
74+#define SASL_ISASL_H
75+
76+#include "visibility.h"
77+
78+#ifdef __cplusplus
79+extern "C" {
80+#endif
81+
82+typedef struct {
83+ unsigned long len;
84+ unsigned char data[1];
85+} sasl_secret_t;
86+
87+typedef struct {
88+ unsigned long id;
89+ int (*proc)(void);
90+ void *context;
91+} sasl_callback_t;
92+
93+/* define the different callback id's we support */
94+#define SASL_CB_USER 1
95+#define SASL_CB_AUTHNAME 2
96+#define SASL_CB_PASS 3
97+#define SASL_CB_LIST_END 4
98+
99+/* Define the error codes we support */
100+#define SASL_OK 0
101+#define SASL_CONTINUE 1
102+#define SASL_ERROR -1
103+#define SASL_BADPARAM -7
104+
105+typedef struct sasl_conn sasl_conn_t;
106+
107+LIBMEMCACHED_LOCAL
108+int sasl_client_init(const sasl_callback_t *callbacks);
109+
110+LIBMEMCACHED_LOCAL
111+void sasl_done(void);
112+
113+LIBMEMCACHED_LOCAL
114+int sasl_client_new(const char *service,
115+ const char *serverFQDN,
116+ const char *iplocalport,
117+ const char *ipremoteport,
118+ const sasl_callback_t *prompt_supp,
119+ unsigned int flags,
120+ sasl_conn_t **pconn);
121+
122+LIBMEMCACHED_LOCAL
123+void sasl_dispose(sasl_conn_t **pconn);
124+
125+LIBMEMCACHED_LOCAL
126+int sasl_client_start(sasl_conn_t *conn,
127+ const char *mechlist,
128+ void **prompt_need,
129+ const char **clientout,
130+ unsigned int *clientoutlen,
131+ const char **mech);
132+
133+LIBMEMCACHED_LOCAL
134+int sasl_client_step(sasl_conn_t *a, const void *b, unsigned int c,
135+ void *d, const void *e, void *f);
136+
137+LIBMEMCACHED_LOCAL
138+const char *sasl_errstring(int saslerr,
139+ const char *langlist,
140+ const char **outlang);
141+#ifdef __cplusplus
142+}
143+#endif
144+
145+#endif
146
147=== modified file 'libmemcached-1.2/sasl.h'
148--- libmemcached-1.2/sasl.h 2013-06-12 08:17:31 +0000
149+++ libmemcached-1.2/sasl.h 2014-06-20 23:47:25 +0000
150@@ -37,11 +37,7 @@
151
152 #pragma once
153
154-#if defined(LIBMEMCACHED_WITH_SASL_SUPPORT) && LIBMEMCACHED_WITH_SASL_SUPPORT
155-# include <sasl/sasl.h>
156-#else
157-# define sasl_callback_t void
158-#endif
159+#include <libmemcached-1.2/isasl.h>
160
161 #ifdef __cplusplus
162 extern "C" {
163
164=== modified file 'libmemcached-1.2/struct/sasl.h'
165--- libmemcached-1.2/struct/sasl.h 2011-12-12 16:59:07 +0000
166+++ libmemcached-1.2/struct/sasl.h 2014-06-20 23:47:25 +0000
167@@ -35,14 +35,10 @@
168 *
169 */
170
171-#if defined(LIBMEMCACHED_WITH_SASL_SUPPORT) && LIBMEMCACHED_WITH_SASL_SUPPORT
172-#include <sasl/sasl.h>
173-#else
174-#define sasl_callback_t void
175-#endif
176-
177 #pragma once
178
179+#include <libmemcached-1.2/isasl.h>
180+
181 struct memcached_sasl_st {
182 sasl_callback_t *callbacks;
183 /*
184
185=== modified file 'libmemcached/include.am'
186--- libmemcached/include.am 2014-02-03 15:21:04 +0000
187+++ libmemcached/include.am 2014-06-20 23:47:25 +0000
188@@ -107,6 +107,7 @@
189 libmemcached_libmemcached_la_SOURCES+= libmemcached/response.cc
190 libmemcached_libmemcached_la_SOURCES+= libmemcached/result.cc
191 libmemcached_libmemcached_la_SOURCES+= libmemcached/sasl.cc
192+libmemcached_libmemcached_la_SOURCES+= libmemcached/sasl_client.cc
193 libmemcached_libmemcached_la_SOURCES+= libmemcached/server.cc
194 libmemcached_libmemcached_la_SOURCES+= libmemcached/server_list.cc
195 libmemcached_libmemcached_la_SOURCES+= libmemcached/server_list.hpp
196
197=== modified file 'libmemcached/sasl.cc'
198--- libmemcached/sasl.cc 2013-06-12 09:23:02 +0000
199+++ libmemcached/sasl.cc 2014-06-20 23:47:25 +0000
200@@ -36,112 +36,25 @@
201 */
202
203 #include "libmemcached/common.h"
204+
205 #include <cassert>
206-
207-#if defined(LIBMEMCACHED_WITH_SASL_SUPPORT) && LIBMEMCACHED_WITH_SASL_SUPPORT
208-
209-#if defined(HAVE_LIBSASL) && HAVE_LIBSASL
210-#include <sasl/sasl.h>
211-#endif
212-
213 #include <pthread.h>
214
215 void memcached_set_sasl_callbacks(memcached_st *shell,
216 const sasl_callback_t *callbacks)
217 {
218- Memcached* self= memcached2Memcached(shell);
219- if (self)
220- {
221- self->sasl.callbacks= const_cast<sasl_callback_t *>(callbacks);
222- self->sasl.is_allocated= false;
223- }
224+ (void)shell;
225+ (void)callbacks;
226 }
227
228 sasl_callback_t *memcached_get_sasl_callbacks(memcached_st *shell)
229 {
230- Memcached* self= memcached2Memcached(shell);
231- if (self)
232- {
233- return self->sasl.callbacks;
234- }
235-
236+ (void)shell;
237 return NULL;
238 }
239
240-/**
241- * Resolve the names for both ends of a connection
242- * @param fd socket to check
243- * @param laddr local address (out)
244- * @param raddr remote address (out)
245- * @return true on success false otherwise (errno contains more info)
246- */
247-static memcached_return_t resolve_names(memcached_instance_st& server, char *laddr, size_t laddr_length, char *raddr, size_t raddr_length)
248-{
249- char host[MEMCACHED_NI_MAXHOST];
250- char port[MEMCACHED_NI_MAXSERV];
251- struct sockaddr_storage saddr;
252- socklen_t salen= sizeof(saddr);
253-
254- if (getsockname(server.fd, (struct sockaddr *)&saddr, &salen) < 0)
255- {
256- return memcached_set_error(server, MEMCACHED_HOST_LOOKUP_FAILURE, MEMCACHED_AT);
257- }
258-
259- if (getnameinfo((struct sockaddr *)&saddr, salen, host, sizeof(host), port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV) < 0)
260- {
261- return memcached_set_error(server, MEMCACHED_HOST_LOOKUP_FAILURE, MEMCACHED_AT);
262- }
263-
264- (void)snprintf(laddr, laddr_length, "%s;%s", host, port);
265- salen= sizeof(saddr);
266-
267- if (getpeername(server.fd, (struct sockaddr *)&saddr, &salen) < 0)
268- {
269- return memcached_set_error(server, MEMCACHED_HOST_LOOKUP_FAILURE, MEMCACHED_AT);
270- }
271-
272- if (getnameinfo((struct sockaddr *)&saddr, salen, host, sizeof(host),
273- port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV) < 0)
274- {
275- return memcached_set_error(server, MEMCACHED_HOST_LOOKUP_FAILURE, MEMCACHED_AT);
276- }
277-
278- (void)snprintf(raddr, raddr_length, "%s;%s", host, port);
279-
280- return MEMCACHED_SUCCESS;
281-}
282-
283-extern "C" {
284-
285-static void sasl_shutdown_function()
286-{
287- sasl_done();
288-}
289-
290-static volatile int sasl_startup_state= SASL_OK;
291-pthread_mutex_t sasl_startup_state_LOCK= PTHREAD_MUTEX_INITIALIZER;
292-static pthread_once_t sasl_startup_once= PTHREAD_ONCE_INIT;
293-static void sasl_startup_function(void)
294-{
295- sasl_startup_state= sasl_client_init(NULL);
296-
297- if (sasl_startup_state == SASL_OK)
298- {
299- (void)atexit(sasl_shutdown_function);
300- }
301-}
302-
303-} // extern "C"
304-
305 memcached_return_t memcached_sasl_authenticate_connection(memcached_instance_st* server)
306 {
307-#if defined(LIBMEMCACHED_WITH_SASL_SUPPORT) && LIBMEMCACHED_WITH_SASL_SUPPORT == 0
308- if (LIBMEMCACHED_WITH_SASL_SUPPORT == 0)
309- {
310- return MEMCACHED_NOT_SUPPORTED;
311- }
312-#endif
313-
314 if (server == NULL)
315 {
316 return MEMCACHED_INVALID_ARGUMENTS;
317@@ -150,14 +63,15 @@
318 /* SANITY CHECK: SASL can only be used with the binary protocol */
319 if (memcached_is_binary(server->root) == false)
320 {
321- return memcached_set_error(*server, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT,
322- memcached_literal_param("memcached_sasl_authenticate_connection() is not supported via the ASCII protocol"));
323+ return memcached_set_error(*server, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT,
324+ memcached_literal_param("memcached_sasl_authenticate_connection() is "
325+ "not supported via the ASCII protocol"));
326 }
327
328 /* Try to get the supported mech from the server. Servers without SASL
329- * support will return UNKNOWN COMMAND, so we can just treat that
330- * as authenticated
331- */
332+ * support will return UNKNOWN COMMAND, so we can just treat that as
333+ * authenticated
334+ */
335 protocol_binary_request_no_extras request= { };
336
337 initialize_binary_request(server, request.message.header);
338@@ -183,7 +97,7 @@
339 * that the server don't support SASL and treat it as success and
340 * let the client fail with the next operation if the error was
341 * caused by another problem....
342- */
343+ */
344 rc= MEMCACHED_SUCCESS;
345 }
346
347@@ -191,33 +105,9 @@
348 }
349 assert_msg(server->fd != INVALID_SOCKET, "Programmer error, invalid socket");
350
351- /* set ip addresses */
352- char laddr[MEMCACHED_NI_MAXHOST + MEMCACHED_NI_MAXSERV];
353- char raddr[MEMCACHED_NI_MAXHOST + MEMCACHED_NI_MAXSERV];
354-
355- if (memcached_failed(rc= resolve_names(*server, laddr, sizeof(laddr), raddr, sizeof(raddr))))
356- {
357- return rc;
358- }
359-
360- int pthread_error;
361- if ((pthread_error= pthread_once(&sasl_startup_once, sasl_startup_function)) != 0)
362- {
363- return memcached_set_errno(*server, pthread_error, MEMCACHED_AT);
364- }
365-
366- (void)pthread_mutex_lock(&sasl_startup_state_LOCK);
367- if (sasl_startup_state != SASL_OK)
368- {
369- const char *sasl_error_msg= sasl_errstring(sasl_startup_state, NULL, NULL);
370- return memcached_set_error(*server, MEMCACHED_AUTH_PROBLEM, MEMCACHED_AT,
371- memcached_string_make_from_cstr(sasl_error_msg));
372- }
373- (void)pthread_mutex_unlock(&sasl_startup_state_LOCK);
374-
375 sasl_conn_t *conn;
376 int ret;
377- if ((ret= sasl_client_new("memcached", server->_hostname, laddr, raddr, server->root->sasl.callbacks, 0, &conn) ) != SASL_OK)
378+ if ((ret= sasl_client_new("memcached", NULL, NULL, NULL, server->root->sasl.callbacks, 0, &conn) ) != SASL_OK)
379 {
380 const char *sasl_error_msg= sasl_errstring(ret, NULL, NULL);
381
382@@ -326,228 +216,109 @@
383 const char *username,
384 const char *password)
385 {
386- if (libmemcached_has_feature(LIBMEMCACHED_FEATURE_HAS_SASL))
387- {
388- Memcached* ptr= memcached2Memcached(shell);
389-
390- if (ptr == NULL or username == NULL or password == NULL)
391- {
392- return MEMCACHED_INVALID_ARGUMENTS;
393- }
394-
395- memcached_return_t ret;
396- if (memcached_failed(ret= memcached_behavior_set(ptr, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, 1)))
397- {
398- return memcached_set_error(*ptr, ret, MEMCACHED_AT, memcached_literal_param("Unable change to binary protocol which is required for SASL."));
399- }
400-
401- memcached_destroy_sasl_auth_data(ptr);
402-
403- sasl_callback_t *callbacks= libmemcached_xcalloc(ptr, 4, sasl_callback_t);
404- size_t password_length= strlen(password);
405- size_t username_length= strlen(username);
406- char *name= (char *)libmemcached_malloc(ptr, username_length +1);
407- sasl_secret_t *secret= (sasl_secret_t*)libmemcached_malloc(ptr, password_length +1 + sizeof(sasl_secret_t));
408-
409- if (callbacks == NULL or name == NULL or secret == NULL)
410- {
411- libmemcached_free(ptr, callbacks);
412- libmemcached_free(ptr, name);
413- libmemcached_free(ptr, secret);
414- return memcached_set_error(*ptr, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT);
415- }
416-
417- secret->len= password_length;
418- memcpy(secret->data, password, password_length);
419- secret->data[password_length]= 0;
420-
421- callbacks[0].id= SASL_CB_USER;
422- callbacks[0].proc= (int (*)())get_username;
423- callbacks[0].context= strncpy(name, username, username_length +1);
424- callbacks[1].id= SASL_CB_AUTHNAME;
425- callbacks[1].proc= (int (*)())get_username;
426- callbacks[1].context= name;
427- callbacks[2].id= SASL_CB_PASS;
428- callbacks[2].proc= (int (*)())get_password;
429- callbacks[2].context= secret;
430- callbacks[3].id= SASL_CB_LIST_END;
431-
432- ptr->sasl.callbacks= callbacks;
433- ptr->sasl.is_allocated= true;
434-
435- return MEMCACHED_SUCCESS;
436- }
437- return MEMCACHED_NOT_SUPPORTED;
438+ Memcached* ptr= memcached2Memcached(shell);
439+
440+ if (ptr == NULL or username == NULL or password == NULL)
441+ {
442+ return MEMCACHED_INVALID_ARGUMENTS;
443+ }
444+
445+ memcached_return_t ret;
446+ if (memcached_failed(ret= memcached_behavior_set(ptr, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, 1)))
447+ {
448+ return memcached_set_error(*ptr, ret, MEMCACHED_AT, memcached_literal_param("Unable change to binary protocol which is required for SASL."));
449+ }
450+
451+ memcached_destroy_sasl_auth_data(ptr);
452+
453+ sasl_callback_t *callbacks= libmemcached_xcalloc(ptr, 4, sasl_callback_t);
454+ size_t password_length= strlen(password);
455+ size_t username_length= strlen(username);
456+ char *name= (char *)libmemcached_malloc(ptr, username_length +1);
457+ sasl_secret_t *secret= (sasl_secret_t*)libmemcached_malloc(ptr, password_length +1 + sizeof(sasl_secret_t));
458+
459+ if (callbacks == NULL or name == NULL or secret == NULL)
460+ {
461+ libmemcached_free(ptr, callbacks);
462+ libmemcached_free(ptr, name);
463+ libmemcached_free(ptr, secret);
464+ return memcached_set_error(*ptr, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT);
465+ }
466+
467+ secret->len= password_length;
468+ memcpy(secret->data, password, password_length);
469+ secret->data[password_length]= 0;
470+
471+ callbacks[0].id= SASL_CB_USER;
472+ callbacks[0].proc= (int (*)())get_username;
473+ callbacks[0].context= strncpy(name, username, username_length +1);
474+ callbacks[1].id= SASL_CB_AUTHNAME;
475+ callbacks[1].proc= (int (*)())get_username;
476+ callbacks[1].context= name;
477+ callbacks[2].id= SASL_CB_PASS;
478+ callbacks[2].proc= (int (*)())get_password;
479+ callbacks[2].context= secret;
480+ callbacks[3].id= SASL_CB_LIST_END;
481+
482+ ptr->sasl.callbacks= callbacks;
483+ ptr->sasl.is_allocated= true;
484+
485+ return MEMCACHED_SUCCESS;
486 }
487
488 memcached_return_t memcached_destroy_sasl_auth_data(memcached_st *shell)
489 {
490- if (libmemcached_has_feature(LIBMEMCACHED_FEATURE_HAS_SASL))
491- {
492- Memcached* ptr= memcached2Memcached(shell);
493- if (ptr == NULL)
494- {
495- return MEMCACHED_INVALID_ARGUMENTS;
496- }
497-
498- if (ptr->sasl.callbacks == NULL)
499- {
500- return MEMCACHED_SUCCESS;
501- }
502-
503- if (ptr->sasl.is_allocated)
504- {
505- libmemcached_free(ptr, ptr->sasl.callbacks[0].context);
506- libmemcached_free(ptr, ptr->sasl.callbacks[2].context);
507- libmemcached_free(ptr, (void*)ptr->sasl.callbacks);
508- ptr->sasl.is_allocated= false;
509- }
510-
511- ptr->sasl.callbacks= NULL;
512-
513+ Memcached* ptr= memcached2Memcached(shell);
514+ if (ptr == NULL)
515+ {
516+ return MEMCACHED_INVALID_ARGUMENTS;
517+ }
518+
519+ if (ptr->sasl.callbacks == NULL)
520+ {
521 return MEMCACHED_SUCCESS;
522 }
523
524- return MEMCACHED_NOT_SUPPORTED;
525+ if (ptr->sasl.is_allocated)
526+ {
527+ libmemcached_free(ptr, ptr->sasl.callbacks[0].context);
528+ libmemcached_free(ptr, ptr->sasl.callbacks[2].context);
529+ libmemcached_free(ptr, (void*)ptr->sasl.callbacks);
530+ ptr->sasl.is_allocated= false;
531+ }
532+
533+ ptr->sasl.callbacks= NULL;
534+
535+ return MEMCACHED_SUCCESS;
536 }
537
538 memcached_return_t memcached_clone_sasl(memcached_st *clone, const memcached_st *source)
539 {
540- if (libmemcached_has_feature(LIBMEMCACHED_FEATURE_HAS_SASL))
541- {
542- if (clone == NULL or source == NULL)
543- {
544- return MEMCACHED_INVALID_ARGUMENTS;
545- }
546-
547- if (source->sasl.callbacks == NULL)
548- {
549- return MEMCACHED_SUCCESS;
550- }
551-
552- /* Hopefully we are using our own callback mechanisms.. */
553- if (source->sasl.callbacks[0].id == SASL_CB_USER &&
554- source->sasl.callbacks[0].proc == (int (*)())get_username &&
555- source->sasl.callbacks[1].id == SASL_CB_AUTHNAME &&
556- source->sasl.callbacks[1].proc == (int (*)())get_username &&
557- source->sasl.callbacks[2].id == SASL_CB_PASS &&
558- source->sasl.callbacks[2].proc == (int (*)())get_password &&
559- source->sasl.callbacks[3].id == SASL_CB_LIST_END)
560- {
561- sasl_secret_t *secret= (sasl_secret_t *)source->sasl.callbacks[2].context;
562- return memcached_set_sasl_auth_data(clone,
563- (const char*)source->sasl.callbacks[0].context,
564- (const char*)secret->data);
565- }
566-
567- /*
568- * But we're not. It may work if we know what the user tries to pass
569- * into the list, but if we don't know the ID we don't know how to handle
570- * the context...
571- */
572- ptrdiff_t total= 0;
573-
574- while (source->sasl.callbacks[total].id != SASL_CB_LIST_END)
575- {
576- switch (source->sasl.callbacks[total].id)
577- {
578- case SASL_CB_USER:
579- case SASL_CB_AUTHNAME:
580- case SASL_CB_PASS:
581- break;
582- default:
583- /* I don't know how to deal with this... */
584- return MEMCACHED_NOT_SUPPORTED;
585- }
586-
587- ++total;
588- }
589-
590- sasl_callback_t *callbacks= libmemcached_xcalloc(clone, total +1, sasl_callback_t);
591- if (callbacks == NULL)
592- {
593- return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
594- }
595- memcpy(callbacks, source->sasl.callbacks, (total + 1) * sizeof(sasl_callback_t));
596-
597- /* Now update the context... */
598- for (ptrdiff_t x= 0; x < total; ++x)
599- {
600- if (callbacks[x].id == SASL_CB_USER || callbacks[x].id == SASL_CB_AUTHNAME)
601- {
602- callbacks[x].context= (sasl_callback_t*)libmemcached_malloc(clone, strlen((const char*)source->sasl.callbacks[x].context));
603-
604- if (callbacks[x].context == NULL)
605- {
606- /* Failed to allocate memory, clean up previously allocated memory */
607- for (ptrdiff_t y= 0; y < x; ++y)
608- {
609- libmemcached_free(clone, clone->sasl.callbacks[y].context);
610- }
611-
612- libmemcached_free(clone, callbacks);
613- return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
614- }
615- strncpy((char*)callbacks[x].context, (const char*)source->sasl.callbacks[x].context, sizeof(callbacks[x].context));
616- }
617- else
618- {
619- sasl_secret_t *src= (sasl_secret_t *)source->sasl.callbacks[x].context;
620- sasl_secret_t *n= (sasl_secret_t*)libmemcached_malloc(clone, src->len + 1 + sizeof(*n));
621- if (n == NULL)
622- {
623- /* Failed to allocate memory, clean up previously allocated memory */
624- for (ptrdiff_t y= 0; y < x; ++y)
625- {
626- libmemcached_free(clone, clone->sasl.callbacks[y].context);
627- }
628-
629- libmemcached_free(clone, callbacks);
630- return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
631- }
632- memcpy(n, src, src->len + 1 + sizeof(*n));
633- callbacks[x].context= n;
634- }
635- }
636-
637- clone->sasl.callbacks= callbacks;
638- clone->sasl.is_allocated= true;
639-
640+ if (clone == NULL or source == NULL)
641+ {
642+ return MEMCACHED_INVALID_ARGUMENTS;
643+ }
644+
645+ if (source->sasl.callbacks == NULL)
646+ {
647 return MEMCACHED_SUCCESS;
648 }
649
650- return MEMCACHED_NOT_SUPPORTED;
651-}
652-
653-#else
654-
655-void memcached_set_sasl_callbacks(memcached_st *, const sasl_callback_t *)
656-{
657-}
658-
659-sasl_callback_t *memcached_get_sasl_callbacks(memcached_st *)
660-{
661- return NULL;
662-}
663-
664-memcached_return_t memcached_set_sasl_auth_data(memcached_st *, const char *, const char *)
665-{
666- return MEMCACHED_NOT_SUPPORTED;
667-}
668-
669-memcached_return_t memcached_clone_sasl(memcached_st *, const memcached_st *)
670-{
671- return MEMCACHED_NOT_SUPPORTED;
672-}
673-
674-memcached_return_t memcached_destroy_sasl_auth_data(memcached_st*)
675-{
676- return MEMCACHED_NOT_SUPPORTED;
677-}
678-
679-memcached_return_t memcached_sasl_authenticate_connection(memcached_instance_st*)
680-{
681- return MEMCACHED_NOT_SUPPORTED;
682-}
683-
684-#endif
685+ /* Only support using our own callback mechanisms.. */
686+ if (source->sasl.callbacks[0].id == SASL_CB_USER &&
687+ source->sasl.callbacks[0].proc == (int (*)())get_username &&
688+ source->sasl.callbacks[1].id == SASL_CB_AUTHNAME &&
689+ source->sasl.callbacks[1].proc == (int (*)())get_username &&
690+ source->sasl.callbacks[2].id == SASL_CB_PASS &&
691+ source->sasl.callbacks[2].proc == (int (*)())get_password &&
692+ source->sasl.callbacks[3].id == SASL_CB_LIST_END)
693+ {
694+ sasl_secret_t *secret= (sasl_secret_t *)source->sasl.callbacks[2].context;
695+ return memcached_set_sasl_auth_data(clone,
696+ (const char*)source->sasl.callbacks[0].context,
697+ (const char*)secret->data);
698+ }
699+
700+ return MEMCACHED_NOT_SUPPORTED;
701+}
702+
703
704=== added file 'libmemcached/sasl_client.cc'
705--- libmemcached/sasl_client.cc 1970-01-01 00:00:00 +0000
706+++ libmemcached/sasl_client.cc 2014-06-20 23:47:25 +0000
707@@ -0,0 +1,192 @@
708+/* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
709+/*
710+ * Copyright (C) 2010 Membase, Inc
711+ * All rights reserved.
712+ *
713+ * Licensed under the Apache License, Version 2.0 (the "License");
714+ * you may not use this file except in compliance with the License.
715+ * You may obtain a copy of the License at
716+ *
717+ * http://www.apache.org/licenses/LICENSE-2.0
718+ *
719+ * Unless required by applicable law or agreed to in writing, software
720+ * distributed under the License is distributed on an "AS IS" BASIS,
721+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
722+ * See the License for the specific language governing permissions and
723+ * limitations under the License.
724+ */
725+
726+// Minimal SASL client that only supports PLAIN authentication.
727+
728+#include <libmemcached-1.2/isasl.h>
729+#include <string.h>
730+#include <stdlib.h>
731+
732+struct sasl_conn {
733+ const sasl_callback_t *callbacks;
734+ char *userdata;
735+};
736+
737+static const char *plain = "PLAIN";
738+
739+LIBMEMCACHED_LOCAL
740+int sasl_client_new(const char *service,
741+ const char *serverFQDN,
742+ const char *iplocalport,
743+ const char *ipremoteport,
744+ const sasl_callback_t *prompt_supp,
745+ unsigned flags,
746+ sasl_conn_t **pconn)
747+{
748+ struct sasl_conn *conn = (sasl_conn *) calloc(1, sizeof(*conn));
749+ if (conn == NULL) {
750+ return SASL_ERROR;
751+ }
752+
753+ conn->callbacks = prompt_supp;
754+ *pconn = conn;
755+
756+ (void)service;
757+ (void)serverFQDN;
758+ (void)iplocalport;
759+ (void)ipremoteport;
760+ (void)flags;
761+
762+ return SASL_OK;
763+}
764+
765+LIBMEMCACHED_LOCAL
766+void sasl_dispose(sasl_conn_t **pconn) {
767+ free((*pconn)->userdata);
768+ free(*pconn);
769+ *pconn = NULL;
770+}
771+
772+LIBMEMCACHED_LOCAL
773+int sasl_client_start(sasl_conn_t *conn,
774+ const char *mechlist,
775+ void **prompt_need,
776+ const char **clientout,
777+ unsigned int*clientoutlen,
778+ const char **mech) {
779+ const char *usernm = NULL;
780+ unsigned int usernmlen;
781+ int i = 0;
782+ int found = 0;
783+ sasl_secret_t *pass;
784+
785+ if (strstr(mechlist, "PLAIN") == NULL) {
786+ return SASL_ERROR;
787+ }
788+
789+ *mech = plain;
790+
791+ /* get the username: */
792+ while (conn->callbacks[i].id != SASL_CB_LIST_END) {
793+ if (conn->callbacks[i].id == SASL_CB_USER) {
794+ int r;
795+ union {
796+ int (*get)(void*, int, const char **, unsigned int*);
797+ int (*proc)(void);
798+ } hack;
799+
800+ hack.proc = conn->callbacks[i].proc;
801+
802+ r = hack.get(conn->callbacks[i].context, SASL_CB_USER,
803+ &usernm, &usernmlen);
804+ if (r != SASL_OK) {
805+ return r;
806+ }
807+ found = 1;
808+ break;
809+ }
810+ ++i;
811+ }
812+
813+ if (!found) {
814+ return SASL_ERROR;
815+ }
816+
817+ found = 0;
818+ i = 0;
819+ while (conn->callbacks[i].id != SASL_CB_LIST_END) {
820+ if (conn->callbacks[i].id == SASL_CB_PASS) {
821+ int r;
822+ union {
823+ int (*get)(sasl_conn_t *, void *, int, sasl_secret_t **);
824+ int (*proc)(void);
825+ } hack;
826+
827+ hack.proc = conn->callbacks[i].proc;
828+
829+ r = hack.get(conn, conn->callbacks[i].context, SASL_CB_PASS,
830+ &pass);
831+ if (r != SASL_OK) {
832+ return r;
833+ }
834+ found = 1;
835+ break;
836+ }
837+ ++i;
838+ }
839+ if (!found) {
840+ return SASL_ERROR;
841+ }
842+
843+ conn->userdata = (char *) calloc(usernmlen + 1 + pass->len + 1, 1);
844+ if (conn->userdata == NULL) {
845+ return SASL_ERROR;
846+ }
847+
848+ memcpy(conn->userdata + 1, usernm, usernmlen);
849+ memcpy(conn->userdata + usernmlen + 2, pass->data, pass->len);
850+ *clientout = conn->userdata;
851+ *clientoutlen = (unsigned int)(usernmlen + 2 + pass->len);
852+
853+ (void)prompt_need;
854+ return SASL_OK;
855+}
856+
857+LIBMEMCACHED_LOCAL
858+void sasl_done(void)
859+{
860+
861+}
862+
863+LIBMEMCACHED_LOCAL
864+int sasl_client_step(sasl_conn_t *a, const void *b, unsigned int c,
865+ void *d, const void *e, void *f)
866+{
867+ (void)a;(void)b;(void)c;(void)d;(void)e;(void)f;
868+ return SASL_ERROR;
869+}
870+
871+LIBMEMCACHED_LOCAL
872+int sasl_client_init(const sasl_callback_t *callbacks)
873+{
874+ (void)callbacks;
875+ return SASL_OK;
876+}
877+
878+LIBMEMCACHED_LOCAL
879+const char *sasl_errstring(int saslerr,
880+ const char *langlist,
881+ const char **outlang)
882+{
883+ (void)langlist;
884+
885+ if (outlang)
886+ {
887+ *outlang= "en-us";
888+ }
889+
890+ switch(saslerr)
891+ {
892+ case SASL_OK: return "successful result";
893+ case SASL_CONTINUE: return "another step is needed in authentication";
894+ case SASL_ERROR: return "generic failure";
895+ case SASL_BADPARAM: return "invalid parameter supplied";
896+ default: return "undefined error!";
897+ }
898+}
899+

Subscribers

People subscribed via source and target branches

to all changes: