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
=== modified file 'bootstrap.sh'
--- bootstrap.sh 2014-02-16 11:31:04 +0000
+++ bootstrap.sh 2014-06-20 23:47:25 +0000
@@ -191,6 +191,9 @@
191 opensuse)191 opensuse)
192 VENDOR_DISTRIBUTION='opensuse'192 VENDOR_DISTRIBUTION='opensuse'
193 ;;193 ;;
194 arch)
195 VENDOR_DISTRIBUTION='arch'
196 ;;
194 *)197 *)
195 die "attempt to set an invalid VENDOR_DISTRIBUTION=$dist"198 die "attempt to set an invalid VENDOR_DISTRIBUTION=$dist"
196 ;;199 ;;
@@ -262,6 +265,9 @@
262 opensuse)265 opensuse)
263 VENDOR_RELEASE="$release"266 VENDOR_RELEASE="$release"
264 ;;267 ;;
268 arch)
269 VENDOR_RELEASE="$release"
270 ;;
265 unknown)271 unknown)
266 die "attempt to set VENDOR_RELEASE without setting VENDOR_DISTRIBUTION"272 die "attempt to set VENDOR_RELEASE without setting VENDOR_DISTRIBUTION"
267 ;;273 ;;
@@ -311,8 +317,11 @@
311 suse)317 suse)
312 VENDOR='suse'318 VENDOR='suse'
313 ;;319 ;;
320 arch)
321 VENDOR='arch'
322 ;;
314 *)323 *)
315 die "An attempt was made to set an invalid VENDOR=$_vendor"324 die "An attempt was made to set an invalid VENDOR=$vendor"
316 ;;325 ;;
317 esac326 esac
318327
319328
=== modified file 'libmemcached-1.2/include.am'
--- libmemcached-1.2/include.am 2013-06-11 12:31:47 +0000
+++ libmemcached-1.2/include.am 2014-06-20 23:47:25 +0000
@@ -33,6 +33,7 @@
33nobase_include_HEADERS+= libmemcached-1.2/flush_buffers.h 33nobase_include_HEADERS+= libmemcached-1.2/flush_buffers.h
34nobase_include_HEADERS+= libmemcached-1.2/get.h 34nobase_include_HEADERS+= libmemcached-1.2/get.h
35nobase_include_HEADERS+= libmemcached-1.2/hash.h 35nobase_include_HEADERS+= libmemcached-1.2/hash.h
36nobase_include_HEADERS+= libmemcached-1.2/isasl.h
36nobase_include_HEADERS+= libmemcached-1.2/limits.h 37nobase_include_HEADERS+= libmemcached-1.2/limits.h
37nobase_include_HEADERS+= libmemcached-1.2/memcached.h 38nobase_include_HEADERS+= libmemcached-1.2/memcached.h
38nobase_include_HEADERS+= libmemcached-1.2/memcached.hpp 39nobase_include_HEADERS+= libmemcached-1.2/memcached.hpp
3940
=== added file 'libmemcached-1.2/isasl.h'
--- libmemcached-1.2/isasl.h 1970-01-01 00:00:00 +0000
+++ libmemcached-1.2/isasl.h 2014-06-20 23:47:25 +0000
@@ -0,0 +1,92 @@
1/* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2/*
3 * Copyright (C) 2010 Membase, Inc
4 * All rights reserved.
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19/* This is a minimalistic SASL implementation */
20#ifndef SASL_ISASL_H
21#define SASL_ISASL_H
22
23#include "visibility.h"
24
25#ifdef __cplusplus
26extern "C" {
27#endif
28
29typedef struct {
30 unsigned long len;
31 unsigned char data[1];
32} sasl_secret_t;
33
34typedef struct {
35 unsigned long id;
36 int (*proc)(void);
37 void *context;
38} sasl_callback_t;
39
40/* define the different callback id's we support */
41#define SASL_CB_USER 1
42#define SASL_CB_AUTHNAME 2
43#define SASL_CB_PASS 3
44#define SASL_CB_LIST_END 4
45
46/* Define the error codes we support */
47#define SASL_OK 0
48#define SASL_CONTINUE 1
49#define SASL_ERROR -1
50#define SASL_BADPARAM -7
51
52typedef struct sasl_conn sasl_conn_t;
53
54LIBMEMCACHED_LOCAL
55int sasl_client_init(const sasl_callback_t *callbacks);
56
57LIBMEMCACHED_LOCAL
58void sasl_done(void);
59
60LIBMEMCACHED_LOCAL
61int sasl_client_new(const char *service,
62 const char *serverFQDN,
63 const char *iplocalport,
64 const char *ipremoteport,
65 const sasl_callback_t *prompt_supp,
66 unsigned int flags,
67 sasl_conn_t **pconn);
68
69LIBMEMCACHED_LOCAL
70void sasl_dispose(sasl_conn_t **pconn);
71
72LIBMEMCACHED_LOCAL
73int sasl_client_start(sasl_conn_t *conn,
74 const char *mechlist,
75 void **prompt_need,
76 const char **clientout,
77 unsigned int *clientoutlen,
78 const char **mech);
79
80LIBMEMCACHED_LOCAL
81int sasl_client_step(sasl_conn_t *a, const void *b, unsigned int c,
82 void *d, const void *e, void *f);
83
84LIBMEMCACHED_LOCAL
85const char *sasl_errstring(int saslerr,
86 const char *langlist,
87 const char **outlang);
88#ifdef __cplusplus
89}
90#endif
91
92#endif
093
=== modified file 'libmemcached-1.2/sasl.h'
--- libmemcached-1.2/sasl.h 2013-06-12 08:17:31 +0000
+++ libmemcached-1.2/sasl.h 2014-06-20 23:47:25 +0000
@@ -37,11 +37,7 @@
3737
38#pragma once38#pragma once
3939
40#if defined(LIBMEMCACHED_WITH_SASL_SUPPORT) && LIBMEMCACHED_WITH_SASL_SUPPORT40#include <libmemcached-1.2/isasl.h>
41# include <sasl/sasl.h>
42#else
43# define sasl_callback_t void
44#endif
4541
46#ifdef __cplusplus42#ifdef __cplusplus
47extern "C" {43extern "C" {
4844
=== modified file 'libmemcached-1.2/struct/sasl.h'
--- libmemcached-1.2/struct/sasl.h 2011-12-12 16:59:07 +0000
+++ libmemcached-1.2/struct/sasl.h 2014-06-20 23:47:25 +0000
@@ -35,14 +35,10 @@
35 *35 *
36 */36 */
3737
38#if defined(LIBMEMCACHED_WITH_SASL_SUPPORT) && LIBMEMCACHED_WITH_SASL_SUPPORT
39#include <sasl/sasl.h>
40#else
41#define sasl_callback_t void
42#endif
43
44#pragma once38#pragma once
4539
40#include <libmemcached-1.2/isasl.h>
41
46struct memcached_sasl_st {42struct memcached_sasl_st {
47 sasl_callback_t *callbacks;43 sasl_callback_t *callbacks;
48 /*44 /*
4945
=== modified file 'libmemcached/include.am'
--- libmemcached/include.am 2014-02-03 15:21:04 +0000
+++ libmemcached/include.am 2014-06-20 23:47:25 +0000
@@ -107,6 +107,7 @@
107libmemcached_libmemcached_la_SOURCES+= libmemcached/response.cc107libmemcached_libmemcached_la_SOURCES+= libmemcached/response.cc
108libmemcached_libmemcached_la_SOURCES+= libmemcached/result.cc108libmemcached_libmemcached_la_SOURCES+= libmemcached/result.cc
109libmemcached_libmemcached_la_SOURCES+= libmemcached/sasl.cc109libmemcached_libmemcached_la_SOURCES+= libmemcached/sasl.cc
110libmemcached_libmemcached_la_SOURCES+= libmemcached/sasl_client.cc
110libmemcached_libmemcached_la_SOURCES+= libmemcached/server.cc111libmemcached_libmemcached_la_SOURCES+= libmemcached/server.cc
111libmemcached_libmemcached_la_SOURCES+= libmemcached/server_list.cc112libmemcached_libmemcached_la_SOURCES+= libmemcached/server_list.cc
112libmemcached_libmemcached_la_SOURCES+= libmemcached/server_list.hpp113libmemcached_libmemcached_la_SOURCES+= libmemcached/server_list.hpp
113114
=== modified file 'libmemcached/sasl.cc'
--- libmemcached/sasl.cc 2013-06-12 09:23:02 +0000
+++ libmemcached/sasl.cc 2014-06-20 23:47:25 +0000
@@ -36,112 +36,25 @@
36 */36 */
3737
38#include "libmemcached/common.h"38#include "libmemcached/common.h"
39
39#include <cassert>40#include <cassert>
40
41#if defined(LIBMEMCACHED_WITH_SASL_SUPPORT) && LIBMEMCACHED_WITH_SASL_SUPPORT
42
43#if defined(HAVE_LIBSASL) && HAVE_LIBSASL
44#include <sasl/sasl.h>
45#endif
46
47#include <pthread.h>41#include <pthread.h>
4842
49void memcached_set_sasl_callbacks(memcached_st *shell,43void memcached_set_sasl_callbacks(memcached_st *shell,
50 const sasl_callback_t *callbacks)44 const sasl_callback_t *callbacks)
51{45{
52 Memcached* self= memcached2Memcached(shell);46 (void)shell;
53 if (self)47 (void)callbacks;
54 {
55 self->sasl.callbacks= const_cast<sasl_callback_t *>(callbacks);
56 self->sasl.is_allocated= false;
57 }
58}48}
5949
60sasl_callback_t *memcached_get_sasl_callbacks(memcached_st *shell)50sasl_callback_t *memcached_get_sasl_callbacks(memcached_st *shell)
61{51{
62 Memcached* self= memcached2Memcached(shell);52 (void)shell;
63 if (self)
64 {
65 return self->sasl.callbacks;
66 }
67
68 return NULL;53 return NULL;
69}54}
7055
71/**
72 * Resolve the names for both ends of a connection
73 * @param fd socket to check
74 * @param laddr local address (out)
75 * @param raddr remote address (out)
76 * @return true on success false otherwise (errno contains more info)
77 */
78static memcached_return_t resolve_names(memcached_instance_st& server, char *laddr, size_t laddr_length, char *raddr, size_t raddr_length)
79{
80 char host[MEMCACHED_NI_MAXHOST];
81 char port[MEMCACHED_NI_MAXSERV];
82 struct sockaddr_storage saddr;
83 socklen_t salen= sizeof(saddr);
84
85 if (getsockname(server.fd, (struct sockaddr *)&saddr, &salen) < 0)
86 {
87 return memcached_set_error(server, MEMCACHED_HOST_LOOKUP_FAILURE, MEMCACHED_AT);
88 }
89
90 if (getnameinfo((struct sockaddr *)&saddr, salen, host, sizeof(host), port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV) < 0)
91 {
92 return memcached_set_error(server, MEMCACHED_HOST_LOOKUP_FAILURE, MEMCACHED_AT);
93 }
94
95 (void)snprintf(laddr, laddr_length, "%s;%s", host, port);
96 salen= sizeof(saddr);
97
98 if (getpeername(server.fd, (struct sockaddr *)&saddr, &salen) < 0)
99 {
100 return memcached_set_error(server, MEMCACHED_HOST_LOOKUP_FAILURE, MEMCACHED_AT);
101 }
102
103 if (getnameinfo((struct sockaddr *)&saddr, salen, host, sizeof(host),
104 port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV) < 0)
105 {
106 return memcached_set_error(server, MEMCACHED_HOST_LOOKUP_FAILURE, MEMCACHED_AT);
107 }
108
109 (void)snprintf(raddr, raddr_length, "%s;%s", host, port);
110
111 return MEMCACHED_SUCCESS;
112}
113
114extern "C" {
115
116static void sasl_shutdown_function()
117{
118 sasl_done();
119}
120
121static volatile int sasl_startup_state= SASL_OK;
122pthread_mutex_t sasl_startup_state_LOCK= PTHREAD_MUTEX_INITIALIZER;
123static pthread_once_t sasl_startup_once= PTHREAD_ONCE_INIT;
124static void sasl_startup_function(void)
125{
126 sasl_startup_state= sasl_client_init(NULL);
127
128 if (sasl_startup_state == SASL_OK)
129 {
130 (void)atexit(sasl_shutdown_function);
131 }
132}
133
134} // extern "C"
135
136memcached_return_t memcached_sasl_authenticate_connection(memcached_instance_st* server)56memcached_return_t memcached_sasl_authenticate_connection(memcached_instance_st* server)
137{57{
138#if defined(LIBMEMCACHED_WITH_SASL_SUPPORT) && LIBMEMCACHED_WITH_SASL_SUPPORT == 0
139 if (LIBMEMCACHED_WITH_SASL_SUPPORT == 0)
140 {
141 return MEMCACHED_NOT_SUPPORTED;
142 }
143#endif
144
145 if (server == NULL)58 if (server == NULL)
146 {59 {
147 return MEMCACHED_INVALID_ARGUMENTS;60 return MEMCACHED_INVALID_ARGUMENTS;
@@ -150,14 +63,15 @@
150 /* SANITY CHECK: SASL can only be used with the binary protocol */63 /* SANITY CHECK: SASL can only be used with the binary protocol */
151 if (memcached_is_binary(server->root) == false)64 if (memcached_is_binary(server->root) == false)
152 {65 {
153 return memcached_set_error(*server, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT,66 return memcached_set_error(*server, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT,
154 memcached_literal_param("memcached_sasl_authenticate_connection() is not supported via the ASCII protocol"));67 memcached_literal_param("memcached_sasl_authenticate_connection() is "
68 "not supported via the ASCII protocol"));
155 }69 }
15670
157 /* Try to get the supported mech from the server. Servers without SASL71 /* Try to get the supported mech from the server. Servers without SASL
158 * support will return UNKNOWN COMMAND, so we can just treat that72 * support will return UNKNOWN COMMAND, so we can just treat that as
159 * as authenticated73 * authenticated
160 */74 */
161 protocol_binary_request_no_extras request= { };75 protocol_binary_request_no_extras request= { };
16276
163 initialize_binary_request(server, request.message.header);77 initialize_binary_request(server, request.message.header);
@@ -183,7 +97,7 @@
183 * that the server don't support SASL and treat it as success and97 * that the server don't support SASL and treat it as success and
184 * let the client fail with the next operation if the error was98 * let the client fail with the next operation if the error was
185 * caused by another problem....99 * caused by another problem....
186 */100 */
187 rc= MEMCACHED_SUCCESS;101 rc= MEMCACHED_SUCCESS;
188 }102 }
189103
@@ -191,33 +105,9 @@
191 }105 }
192 assert_msg(server->fd != INVALID_SOCKET, "Programmer error, invalid socket");106 assert_msg(server->fd != INVALID_SOCKET, "Programmer error, invalid socket");
193107
194 /* set ip addresses */
195 char laddr[MEMCACHED_NI_MAXHOST + MEMCACHED_NI_MAXSERV];
196 char raddr[MEMCACHED_NI_MAXHOST + MEMCACHED_NI_MAXSERV];
197
198 if (memcached_failed(rc= resolve_names(*server, laddr, sizeof(laddr), raddr, sizeof(raddr))))
199 {
200 return rc;
201 }
202
203 int pthread_error;
204 if ((pthread_error= pthread_once(&sasl_startup_once, sasl_startup_function)) != 0)
205 {
206 return memcached_set_errno(*server, pthread_error, MEMCACHED_AT);
207 }
208
209 (void)pthread_mutex_lock(&sasl_startup_state_LOCK);
210 if (sasl_startup_state != SASL_OK)
211 {
212 const char *sasl_error_msg= sasl_errstring(sasl_startup_state, NULL, NULL);
213 return memcached_set_error(*server, MEMCACHED_AUTH_PROBLEM, MEMCACHED_AT,
214 memcached_string_make_from_cstr(sasl_error_msg));
215 }
216 (void)pthread_mutex_unlock(&sasl_startup_state_LOCK);
217
218 sasl_conn_t *conn;108 sasl_conn_t *conn;
219 int ret;109 int ret;
220 if ((ret= sasl_client_new("memcached", server->_hostname, laddr, raddr, server->root->sasl.callbacks, 0, &conn) ) != SASL_OK)110 if ((ret= sasl_client_new("memcached", NULL, NULL, NULL, server->root->sasl.callbacks, 0, &conn) ) != SASL_OK)
221 {111 {
222 const char *sasl_error_msg= sasl_errstring(ret, NULL, NULL);112 const char *sasl_error_msg= sasl_errstring(ret, NULL, NULL);
223113
@@ -326,228 +216,109 @@
326 const char *username,216 const char *username,
327 const char *password)217 const char *password)
328{218{
329 if (libmemcached_has_feature(LIBMEMCACHED_FEATURE_HAS_SASL))219 Memcached* ptr= memcached2Memcached(shell);
330 {220
331 Memcached* ptr= memcached2Memcached(shell);221 if (ptr == NULL or username == NULL or password == NULL)
332222 {
333 if (ptr == NULL or username == NULL or password == NULL)223 return MEMCACHED_INVALID_ARGUMENTS;
334 {224 }
335 return MEMCACHED_INVALID_ARGUMENTS;225
336 }226 memcached_return_t ret;
337227 if (memcached_failed(ret= memcached_behavior_set(ptr, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, 1)))
338 memcached_return_t ret;228 {
339 if (memcached_failed(ret= memcached_behavior_set(ptr, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, 1)))229 return memcached_set_error(*ptr, ret, MEMCACHED_AT, memcached_literal_param("Unable change to binary protocol which is required for SASL."));
340 {230 }
341 return memcached_set_error(*ptr, ret, MEMCACHED_AT, memcached_literal_param("Unable change to binary protocol which is required for SASL."));231
342 }232 memcached_destroy_sasl_auth_data(ptr);
343233
344 memcached_destroy_sasl_auth_data(ptr);234 sasl_callback_t *callbacks= libmemcached_xcalloc(ptr, 4, sasl_callback_t);
345235 size_t password_length= strlen(password);
346 sasl_callback_t *callbacks= libmemcached_xcalloc(ptr, 4, sasl_callback_t);236 size_t username_length= strlen(username);
347 size_t password_length= strlen(password);237 char *name= (char *)libmemcached_malloc(ptr, username_length +1);
348 size_t username_length= strlen(username);238 sasl_secret_t *secret= (sasl_secret_t*)libmemcached_malloc(ptr, password_length +1 + sizeof(sasl_secret_t));
349 char *name= (char *)libmemcached_malloc(ptr, username_length +1);239
350 sasl_secret_t *secret= (sasl_secret_t*)libmemcached_malloc(ptr, password_length +1 + sizeof(sasl_secret_t));240 if (callbacks == NULL or name == NULL or secret == NULL)
351241 {
352 if (callbacks == NULL or name == NULL or secret == NULL)242 libmemcached_free(ptr, callbacks);
353 {243 libmemcached_free(ptr, name);
354 libmemcached_free(ptr, callbacks);244 libmemcached_free(ptr, secret);
355 libmemcached_free(ptr, name);245 return memcached_set_error(*ptr, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT);
356 libmemcached_free(ptr, secret);246 }
357 return memcached_set_error(*ptr, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT);247
358 }248 secret->len= password_length;
359249 memcpy(secret->data, password, password_length);
360 secret->len= password_length;250 secret->data[password_length]= 0;
361 memcpy(secret->data, password, password_length);251
362 secret->data[password_length]= 0;252 callbacks[0].id= SASL_CB_USER;
363253 callbacks[0].proc= (int (*)())get_username;
364 callbacks[0].id= SASL_CB_USER;254 callbacks[0].context= strncpy(name, username, username_length +1);
365 callbacks[0].proc= (int (*)())get_username;255 callbacks[1].id= SASL_CB_AUTHNAME;
366 callbacks[0].context= strncpy(name, username, username_length +1);256 callbacks[1].proc= (int (*)())get_username;
367 callbacks[1].id= SASL_CB_AUTHNAME;257 callbacks[1].context= name;
368 callbacks[1].proc= (int (*)())get_username;258 callbacks[2].id= SASL_CB_PASS;
369 callbacks[1].context= name;259 callbacks[2].proc= (int (*)())get_password;
370 callbacks[2].id= SASL_CB_PASS;260 callbacks[2].context= secret;
371 callbacks[2].proc= (int (*)())get_password;261 callbacks[3].id= SASL_CB_LIST_END;
372 callbacks[2].context= secret;262
373 callbacks[3].id= SASL_CB_LIST_END;263 ptr->sasl.callbacks= callbacks;
374264 ptr->sasl.is_allocated= true;
375 ptr->sasl.callbacks= callbacks;265
376 ptr->sasl.is_allocated= true;266 return MEMCACHED_SUCCESS;
377
378 return MEMCACHED_SUCCESS;
379 }
380 return MEMCACHED_NOT_SUPPORTED;
381}267}
382268
383memcached_return_t memcached_destroy_sasl_auth_data(memcached_st *shell)269memcached_return_t memcached_destroy_sasl_auth_data(memcached_st *shell)
384{270{
385 if (libmemcached_has_feature(LIBMEMCACHED_FEATURE_HAS_SASL))271 Memcached* ptr= memcached2Memcached(shell);
386 {272 if (ptr == NULL)
387 Memcached* ptr= memcached2Memcached(shell);273 {
388 if (ptr == NULL)274 return MEMCACHED_INVALID_ARGUMENTS;
389 {275 }
390 return MEMCACHED_INVALID_ARGUMENTS;276
391 }277 if (ptr->sasl.callbacks == NULL)
392278 {
393 if (ptr->sasl.callbacks == NULL)
394 {
395 return MEMCACHED_SUCCESS;
396 }
397
398 if (ptr->sasl.is_allocated)
399 {
400 libmemcached_free(ptr, ptr->sasl.callbacks[0].context);
401 libmemcached_free(ptr, ptr->sasl.callbacks[2].context);
402 libmemcached_free(ptr, (void*)ptr->sasl.callbacks);
403 ptr->sasl.is_allocated= false;
404 }
405
406 ptr->sasl.callbacks= NULL;
407
408 return MEMCACHED_SUCCESS;279 return MEMCACHED_SUCCESS;
409 }280 }
410281
411 return MEMCACHED_NOT_SUPPORTED;282 if (ptr->sasl.is_allocated)
283 {
284 libmemcached_free(ptr, ptr->sasl.callbacks[0].context);
285 libmemcached_free(ptr, ptr->sasl.callbacks[2].context);
286 libmemcached_free(ptr, (void*)ptr->sasl.callbacks);
287 ptr->sasl.is_allocated= false;
288 }
289
290 ptr->sasl.callbacks= NULL;
291
292 return MEMCACHED_SUCCESS;
412}293}
413294
414memcached_return_t memcached_clone_sasl(memcached_st *clone, const memcached_st *source)295memcached_return_t memcached_clone_sasl(memcached_st *clone, const memcached_st *source)
415{296{
416 if (libmemcached_has_feature(LIBMEMCACHED_FEATURE_HAS_SASL))297 if (clone == NULL or source == NULL)
417 {298 {
418 if (clone == NULL or source == NULL)299 return MEMCACHED_INVALID_ARGUMENTS;
419 {300 }
420 return MEMCACHED_INVALID_ARGUMENTS;301
421 }302 if (source->sasl.callbacks == NULL)
422303 {
423 if (source->sasl.callbacks == NULL)
424 {
425 return MEMCACHED_SUCCESS;
426 }
427
428 /* Hopefully we are using our own callback mechanisms.. */
429 if (source->sasl.callbacks[0].id == SASL_CB_USER &&
430 source->sasl.callbacks[0].proc == (int (*)())get_username &&
431 source->sasl.callbacks[1].id == SASL_CB_AUTHNAME &&
432 source->sasl.callbacks[1].proc == (int (*)())get_username &&
433 source->sasl.callbacks[2].id == SASL_CB_PASS &&
434 source->sasl.callbacks[2].proc == (int (*)())get_password &&
435 source->sasl.callbacks[3].id == SASL_CB_LIST_END)
436 {
437 sasl_secret_t *secret= (sasl_secret_t *)source->sasl.callbacks[2].context;
438 return memcached_set_sasl_auth_data(clone,
439 (const char*)source->sasl.callbacks[0].context,
440 (const char*)secret->data);
441 }
442
443 /*
444 * But we're not. It may work if we know what the user tries to pass
445 * into the list, but if we don't know the ID we don't know how to handle
446 * the context...
447 */
448 ptrdiff_t total= 0;
449
450 while (source->sasl.callbacks[total].id != SASL_CB_LIST_END)
451 {
452 switch (source->sasl.callbacks[total].id)
453 {
454 case SASL_CB_USER:
455 case SASL_CB_AUTHNAME:
456 case SASL_CB_PASS:
457 break;
458 default:
459 /* I don't know how to deal with this... */
460 return MEMCACHED_NOT_SUPPORTED;
461 }
462
463 ++total;
464 }
465
466 sasl_callback_t *callbacks= libmemcached_xcalloc(clone, total +1, sasl_callback_t);
467 if (callbacks == NULL)
468 {
469 return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
470 }
471 memcpy(callbacks, source->sasl.callbacks, (total + 1) * sizeof(sasl_callback_t));
472
473 /* Now update the context... */
474 for (ptrdiff_t x= 0; x < total; ++x)
475 {
476 if (callbacks[x].id == SASL_CB_USER || callbacks[x].id == SASL_CB_AUTHNAME)
477 {
478 callbacks[x].context= (sasl_callback_t*)libmemcached_malloc(clone, strlen((const char*)source->sasl.callbacks[x].context));
479
480 if (callbacks[x].context == NULL)
481 {
482 /* Failed to allocate memory, clean up previously allocated memory */
483 for (ptrdiff_t y= 0; y < x; ++y)
484 {
485 libmemcached_free(clone, clone->sasl.callbacks[y].context);
486 }
487
488 libmemcached_free(clone, callbacks);
489 return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
490 }
491 strncpy((char*)callbacks[x].context, (const char*)source->sasl.callbacks[x].context, sizeof(callbacks[x].context));
492 }
493 else
494 {
495 sasl_secret_t *src= (sasl_secret_t *)source->sasl.callbacks[x].context;
496 sasl_secret_t *n= (sasl_secret_t*)libmemcached_malloc(clone, src->len + 1 + sizeof(*n));
497 if (n == NULL)
498 {
499 /* Failed to allocate memory, clean up previously allocated memory */
500 for (ptrdiff_t y= 0; y < x; ++y)
501 {
502 libmemcached_free(clone, clone->sasl.callbacks[y].context);
503 }
504
505 libmemcached_free(clone, callbacks);
506 return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
507 }
508 memcpy(n, src, src->len + 1 + sizeof(*n));
509 callbacks[x].context= n;
510 }
511 }
512
513 clone->sasl.callbacks= callbacks;
514 clone->sasl.is_allocated= true;
515
516 return MEMCACHED_SUCCESS;304 return MEMCACHED_SUCCESS;
517 }305 }
518306
519 return MEMCACHED_NOT_SUPPORTED;307 /* Only support using our own callback mechanisms.. */
520}308 if (source->sasl.callbacks[0].id == SASL_CB_USER &&
521309 source->sasl.callbacks[0].proc == (int (*)())get_username &&
522#else310 source->sasl.callbacks[1].id == SASL_CB_AUTHNAME &&
523311 source->sasl.callbacks[1].proc == (int (*)())get_username &&
524void memcached_set_sasl_callbacks(memcached_st *, const sasl_callback_t *)312 source->sasl.callbacks[2].id == SASL_CB_PASS &&
525{313 source->sasl.callbacks[2].proc == (int (*)())get_password &&
526}314 source->sasl.callbacks[3].id == SASL_CB_LIST_END)
527315 {
528sasl_callback_t *memcached_get_sasl_callbacks(memcached_st *)316 sasl_secret_t *secret= (sasl_secret_t *)source->sasl.callbacks[2].context;
529{317 return memcached_set_sasl_auth_data(clone,
530 return NULL;318 (const char*)source->sasl.callbacks[0].context,
531}319 (const char*)secret->data);
532320 }
533memcached_return_t memcached_set_sasl_auth_data(memcached_st *, const char *, const char *)321
534{322 return MEMCACHED_NOT_SUPPORTED;
535 return MEMCACHED_NOT_SUPPORTED;323}
536}324
537
538memcached_return_t memcached_clone_sasl(memcached_st *, const memcached_st *)
539{
540 return MEMCACHED_NOT_SUPPORTED;
541}
542
543memcached_return_t memcached_destroy_sasl_auth_data(memcached_st*)
544{
545 return MEMCACHED_NOT_SUPPORTED;
546}
547
548memcached_return_t memcached_sasl_authenticate_connection(memcached_instance_st*)
549{
550 return MEMCACHED_NOT_SUPPORTED;
551}
552
553#endif
554325
=== added file 'libmemcached/sasl_client.cc'
--- libmemcached/sasl_client.cc 1970-01-01 00:00:00 +0000
+++ libmemcached/sasl_client.cc 2014-06-20 23:47:25 +0000
@@ -0,0 +1,192 @@
1/* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2/*
3 * Copyright (C) 2010 Membase, Inc
4 * All rights reserved.
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19// Minimal SASL client that only supports PLAIN authentication.
20
21#include <libmemcached-1.2/isasl.h>
22#include <string.h>
23#include <stdlib.h>
24
25struct sasl_conn {
26 const sasl_callback_t *callbacks;
27 char *userdata;
28};
29
30static const char *plain = "PLAIN";
31
32LIBMEMCACHED_LOCAL
33int sasl_client_new(const char *service,
34 const char *serverFQDN,
35 const char *iplocalport,
36 const char *ipremoteport,
37 const sasl_callback_t *prompt_supp,
38 unsigned flags,
39 sasl_conn_t **pconn)
40{
41 struct sasl_conn *conn = (sasl_conn *) calloc(1, sizeof(*conn));
42 if (conn == NULL) {
43 return SASL_ERROR;
44 }
45
46 conn->callbacks = prompt_supp;
47 *pconn = conn;
48
49 (void)service;
50 (void)serverFQDN;
51 (void)iplocalport;
52 (void)ipremoteport;
53 (void)flags;
54
55 return SASL_OK;
56}
57
58LIBMEMCACHED_LOCAL
59void sasl_dispose(sasl_conn_t **pconn) {
60 free((*pconn)->userdata);
61 free(*pconn);
62 *pconn = NULL;
63}
64
65LIBMEMCACHED_LOCAL
66int sasl_client_start(sasl_conn_t *conn,
67 const char *mechlist,
68 void **prompt_need,
69 const char **clientout,
70 unsigned int*clientoutlen,
71 const char **mech) {
72 const char *usernm = NULL;
73 unsigned int usernmlen;
74 int i = 0;
75 int found = 0;
76 sasl_secret_t *pass;
77
78 if (strstr(mechlist, "PLAIN") == NULL) {
79 return SASL_ERROR;
80 }
81
82 *mech = plain;
83
84 /* get the username: */
85 while (conn->callbacks[i].id != SASL_CB_LIST_END) {
86 if (conn->callbacks[i].id == SASL_CB_USER) {
87 int r;
88 union {
89 int (*get)(void*, int, const char **, unsigned int*);
90 int (*proc)(void);
91 } hack;
92
93 hack.proc = conn->callbacks[i].proc;
94
95 r = hack.get(conn->callbacks[i].context, SASL_CB_USER,
96 &usernm, &usernmlen);
97 if (r != SASL_OK) {
98 return r;
99 }
100 found = 1;
101 break;
102 }
103 ++i;
104 }
105
106 if (!found) {
107 return SASL_ERROR;
108 }
109
110 found = 0;
111 i = 0;
112 while (conn->callbacks[i].id != SASL_CB_LIST_END) {
113 if (conn->callbacks[i].id == SASL_CB_PASS) {
114 int r;
115 union {
116 int (*get)(sasl_conn_t *, void *, int, sasl_secret_t **);
117 int (*proc)(void);
118 } hack;
119
120 hack.proc = conn->callbacks[i].proc;
121
122 r = hack.get(conn, conn->callbacks[i].context, SASL_CB_PASS,
123 &pass);
124 if (r != SASL_OK) {
125 return r;
126 }
127 found = 1;
128 break;
129 }
130 ++i;
131 }
132 if (!found) {
133 return SASL_ERROR;
134 }
135
136 conn->userdata = (char *) calloc(usernmlen + 1 + pass->len + 1, 1);
137 if (conn->userdata == NULL) {
138 return SASL_ERROR;
139 }
140
141 memcpy(conn->userdata + 1, usernm, usernmlen);
142 memcpy(conn->userdata + usernmlen + 2, pass->data, pass->len);
143 *clientout = conn->userdata;
144 *clientoutlen = (unsigned int)(usernmlen + 2 + pass->len);
145
146 (void)prompt_need;
147 return SASL_OK;
148}
149
150LIBMEMCACHED_LOCAL
151void sasl_done(void)
152{
153
154}
155
156LIBMEMCACHED_LOCAL
157int sasl_client_step(sasl_conn_t *a, const void *b, unsigned int c,
158 void *d, const void *e, void *f)
159{
160 (void)a;(void)b;(void)c;(void)d;(void)e;(void)f;
161 return SASL_ERROR;
162}
163
164LIBMEMCACHED_LOCAL
165int sasl_client_init(const sasl_callback_t *callbacks)
166{
167 (void)callbacks;
168 return SASL_OK;
169}
170
171LIBMEMCACHED_LOCAL
172const char *sasl_errstring(int saslerr,
173 const char *langlist,
174 const char **outlang)
175{
176 (void)langlist;
177
178 if (outlang)
179 {
180 *outlang= "en-us";
181 }
182
183 switch(saslerr)
184 {
185 case SASL_OK: return "successful result";
186 case SASL_CONTINUE: return "another step is needed in authentication";
187 case SASL_ERROR: return "generic failure";
188 case SASL_BADPARAM: return "invalid parameter supplied";
189 default: return "undefined error!";
190 }
191}
192

Subscribers

People subscribed via source and target branches

to all changes: