X-Git-Url: https://git.m6w6.name/?a=blobdiff_plain;f=libmemcached%2Fsasl.c;h=434d2db6af7ccd2d97a0d41b08cc50b112a5c28c;hb=7c8b8a571a25e21046d00cd2ef7897504a5ef939;hp=85edeb3d18e3cbbe8e4fbc76f10c55eb86bfae1e;hpb=cf630fa0430ea62a93a8ed8c2845c68590d09ed1;p=m6w6%2Flibmemcached diff --git a/libmemcached/sasl.c b/libmemcached/sasl.c index 85edeb3d..434d2db6 100644 --- a/libmemcached/sasl.c +++ b/libmemcached/sasl.c @@ -1,29 +1,53 @@ -/* LibMemcached - * Copyright (C) 2006-2010 Brian Aker - * All rights reserved. +/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: + * + * Libmemcached library * - * Use and distribution licensed under the BSD license. See - * the COPYING file in the parent directory for full text. + * Copyright (C) 2011 Data Differential, http://datadifferential.com/ + * Copyright (C) 2006-2009 Brian Aker All rights reserved. * - * Summary: interface for memcached server - * Description: main include file for libmemcached + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * * The names of its contributors may not be used to endorse or + * promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ -#include "common.h" + +#include +#include void memcached_set_sasl_callbacks(memcached_st *ptr, const sasl_callback_t *callbacks) { - ptr->sasl->callbacks= callbacks; - ptr->sasl->is_allocated= false; + ptr->sasl.callbacks= callbacks; + ptr->sasl.is_allocated= false; } const sasl_callback_t *memcached_get_sasl_callbacks(memcached_st *ptr) { - if (ptr->sasl) - return ptr->sasl->callbacks; - - return NULL; + return ptr->sasl.callbacks; } /** @@ -33,41 +57,46 @@ const sasl_callback_t *memcached_get_sasl_callbacks(memcached_st *ptr) * @param raddr remote address (out) * @return true on success false otherwise (errno contains more info) */ -static bool resolve_names(int fd, char *laddr, char *raddr) +static memcached_return_t resolve_names(int fd, char *laddr, size_t laddr_length, char *raddr, size_t raddr_length) { char host[NI_MAXHOST]; char port[NI_MAXSERV]; struct sockaddr_storage saddr; socklen_t salen= sizeof(saddr); - if ((getsockname(fd, (struct sockaddr *)&saddr, &salen) < 0) || - (getnameinfo((struct sockaddr *)&saddr, salen, host, sizeof(host), - port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV) < 0)) + if (getsockname(fd, (struct sockaddr *)&saddr, &salen) < 0) { - return false; + return MEMCACHED_ERRNO; } - (void)sprintf(laddr, "%s;%s", host, port); + if (getnameinfo((struct sockaddr *)&saddr, salen, host, sizeof(host), port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV) < 0) + { + return MEMCACHED_HOST_LOOKUP_FAILURE; + } + + (void)snprintf(laddr, laddr_length, "%s;%s", host, port); salen= sizeof(saddr); - if ((getpeername(fd, (struct sockaddr *)&saddr, &salen) < 0) || - (getnameinfo((struct sockaddr *)&saddr, salen, host, sizeof(host), - port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV) < 0)) + if (getpeername(fd, (struct sockaddr *)&saddr, &salen) < 0) + { + return MEMCACHED_ERRNO; + } + + if (getnameinfo((struct sockaddr *)&saddr, salen, host, sizeof(host), + port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV) < 0) { - return false; + return MEMCACHED_HOST_LOOKUP_FAILURE; } - (void)sprintf(raddr, "%s;%s", host, port); + (void)snprintf(raddr, raddr_length, "%s;%s", host, port); - return true; + return MEMCACHED_SUCCESS; } memcached_return_t memcached_sasl_authenticate_connection(memcached_server_st *server) { - memcached_return_t rc; - /* SANITY CHECK: SASL can only be used with the binary protocol */ - unlikely (!server->root->flags.binary_protocol) + if (!server->root->flags.binary_protocol) return MEMCACHED_FAILURE; /* Try to get the supported mech from the server. Servers without SASL @@ -90,8 +119,8 @@ memcached_return_t memcached_sasl_authenticate_connection(memcached_server_st *s memcached_server_response_increment(server); char mech[MEMCACHED_MAX_BUFFER]; - rc= memcached_response(server, mech, sizeof(mech), NULL); - if (rc != MEMCACHED_SUCCESS) + memcached_return_t rc= memcached_response(server, mech, sizeof(mech), NULL); + if (memcached_failed(rc)) { if (rc == MEMCACHED_PROTOCOL_ERROR) { @@ -111,15 +140,13 @@ memcached_return_t memcached_sasl_authenticate_connection(memcached_server_st *s char laddr[NI_MAXHOST + NI_MAXSERV]; char raddr[NI_MAXHOST + NI_MAXSERV]; - unlikely (!resolve_names(server->fd, laddr, raddr)) + if (memcached_failed(rc= resolve_names(server->fd, laddr, sizeof(laddr), raddr, sizeof(raddr)))) { - server->cached_errno= errno; - return MEMCACHED_ERRNO; + return rc; } sasl_conn_t *conn; - int ret= sasl_client_new("memcached", server->hostname, laddr, raddr, - server->root->sasl->callbacks, 0, &conn); + int ret= sasl_client_new("memcached", server->hostname, laddr, raddr, server->root->sasl.callbacks, 0, &conn); if (ret != SASL_OK) { return MEMCACHED_AUTH_PROBLEM; @@ -144,12 +171,12 @@ memcached_return_t memcached_sasl_authenticate_connection(memcached_server_st *s do { /* send the packet */ - struct __write_vector_st vector[]= - { - { .length= sizeof(request.bytes), .buffer= request.bytes }, - { .length= keylen, .buffer= chosenmech }, - { .length= len, .buffer= data } - }; + struct libmemcached_io_vector_st vector[]= + { + { .length= sizeof(request.bytes), .buffer= request.bytes }, + { .length= keylen, .buffer= chosenmech }, + { .length= len, .buffer= data } + }; if (memcached_io_writev(server, vector, 3, true) == -1) { @@ -221,93 +248,86 @@ memcached_return_t memcached_set_sasl_auth_data(memcached_st *ptr, const char *password) { if (ptr == NULL || username == NULL || - password == NULL || ptr->sasl->callbacks != NULL) + password == NULL || ptr->sasl.callbacks != NULL) { return MEMCACHED_FAILURE; } - sasl_callback_t *cb= libmemcached_calloc(ptr, 4, sizeof(sasl_callback_t)); - char *name= libmemcached_malloc(ptr, strlen(username) + 1); - sasl_secret_t *secret= libmemcached_malloc(ptr, strlen(password) + 1 + sizeof(*secret)) -; - if (cb == NULL || name == NULL || secret == NULL) + sasl_callback_t *callbacks= libmemcached_calloc(ptr, 4, sizeof(sasl_callback_t)); + size_t password_length= strlen(password); + size_t username_length= strlen(username); + char *name= libmemcached_malloc(ptr, username_length +1); + sasl_secret_t *secret= libmemcached_malloc(ptr, password_length +1 + sizeof(sasl_secret_t)); + + if (callbacks == NULL || name == NULL || secret == NULL) { - libmemcached_free(ptr, cb); + libmemcached_free(ptr, callbacks); libmemcached_free(ptr, name); libmemcached_free(ptr, secret); return MEMCACHED_MEMORY_ALLOCATION_FAILURE; } - secret->len= strlen(password); - strcpy((void*)secret->data, password); + secret->len= password_length; + memcpy(secret->data, password, password_length); + secret->data[password_length]= 0; - cb[0].id= SASL_CB_USER; - cb[0].proc= get_username; - cb[0].context= strcpy(name, username); - cb[1].id= SASL_CB_AUTHNAME; - cb[1].proc= get_username; - cb[1].context= name; - cb[2].id= SASL_CB_PASS; - cb[2].proc= get_password; - cb[2].context= secret; - cb[3].id= SASL_CB_LIST_END; + callbacks[0].id= SASL_CB_USER; + callbacks[0].proc= get_username; + callbacks[0].context= strncpy(name, username, username_length +1); + callbacks[1].id= SASL_CB_AUTHNAME; + callbacks[1].proc= get_username; + callbacks[1].context= name; + callbacks[2].id= SASL_CB_PASS; + callbacks[2].proc= get_password; + callbacks[2].context= secret; + callbacks[3].id= SASL_CB_LIST_END; - ptr->sasl->callbacks= cb; - ptr->sasl->is_allocated= true; + ptr->sasl.callbacks= callbacks; + ptr->sasl.is_allocated= true; return MEMCACHED_SUCCESS; } memcached_return_t memcached_destroy_sasl_auth_data(memcached_st *ptr) { - if (ptr == NULL || ptr->sasl->callbacks == NULL) + if (ptr == NULL || ptr->sasl.callbacks == NULL) { return MEMCACHED_FAILURE; } - if (ptr->sasl->is_allocated) + if (ptr->sasl.is_allocated) { - libmemcached_free(ptr, ptr->sasl->callbacks[0].context); - libmemcached_free(ptr, ptr->sasl->callbacks[2].context); - libmemcached_free(ptr, (void*)ptr->sasl->callbacks); - ptr->sasl->is_allocated= false; + libmemcached_free(ptr, ptr->sasl.callbacks[0].context); + libmemcached_free(ptr, ptr->sasl.callbacks[2].context); + libmemcached_free(ptr, (void*)ptr->sasl.callbacks); + ptr->sasl.is_allocated= false; } - ptr->sasl->callbacks= NULL; - libmemcached_free(ptr, ptr->sasl); - ptr->sasl= NULL; + ptr->sasl.callbacks= NULL; return MEMCACHED_SUCCESS; } memcached_return_t memcached_clone_sasl(memcached_st *clone, const memcached_st *source) { - if (source->sasl == NULL) + + if (source->sasl.callbacks == NULL) { return MEMCACHED_SUCCESS; } - else - { - clone->sasl= libmemcached_malloc(source, sizeof(struct memcached_sasl_st)); - - if (clone->sasl == NULL) - { - return MEMCACHED_MEMORY_ALLOCATION_FAILURE; - } - } /* Hopefully we are using our own callback mechanisms.. */ - if (source->sasl->callbacks[0].id == SASL_CB_USER && - source->sasl->callbacks[0].proc == get_username && - source->sasl->callbacks[1].id == SASL_CB_AUTHNAME && - source->sasl->callbacks[1].proc == get_username && - source->sasl->callbacks[2].id == SASL_CB_PASS && - source->sasl->callbacks[2].proc == get_password && - source->sasl->callbacks[3].id == SASL_CB_LIST_END) + if (source->sasl.callbacks[0].id == SASL_CB_USER && + source->sasl.callbacks[0].proc == get_username && + source->sasl.callbacks[1].id == SASL_CB_AUTHNAME && + source->sasl.callbacks[1].proc == get_username && + source->sasl.callbacks[2].id == SASL_CB_PASS && + source->sasl.callbacks[2].proc == get_password && + source->sasl.callbacks[3].id == SASL_CB_LIST_END) { - sasl_secret_t *secret= source->sasl->callbacks[2].context; + sasl_secret_t *secret= source->sasl.callbacks[2].context; return memcached_set_sasl_auth_data(clone, - source->sasl->callbacks[0].context, + source->sasl.callbacks[0].context, (const char*)secret->data); } @@ -318,9 +338,9 @@ memcached_return_t memcached_clone_sasl(memcached_st *clone, const memcached_st */ size_t total= 0; - while (source->sasl->callbacks[total].id != SASL_CB_LIST_END) + while (source->sasl.callbacks[total].id != SASL_CB_LIST_END) { - switch (source->sasl->callbacks[total].id) + switch (source->sasl.callbacks[total].id) { case SASL_CB_USER: case SASL_CB_AUTHNAME: @@ -334,55 +354,55 @@ memcached_return_t memcached_clone_sasl(memcached_st *clone, const memcached_st ++total; } - sasl_callback_t *cb= libmemcached_calloc(clone, total + 1, sizeof(sasl_callback_t)); - if (cb == NULL) + sasl_callback_t *callbacks= libmemcached_calloc(clone, total + 1, sizeof(sasl_callback_t)); + if (callbacks == NULL) { return MEMCACHED_MEMORY_ALLOCATION_FAILURE; } - memcpy(cb, source->sasl->callbacks, (total + 1) * sizeof(sasl_callback_t)); + memcpy(callbacks, source->sasl.callbacks, (total + 1) * sizeof(sasl_callback_t)); /* Now update the context... */ for (size_t x= 0; x < total; ++x) { - if (cb[x].id == SASL_CB_USER || cb[x].id == SASL_CB_AUTHNAME) + if (callbacks[x].id == SASL_CB_USER || callbacks[x].id == SASL_CB_AUTHNAME) { - cb[x].context= libmemcached_malloc(clone, strlen(source->sasl->callbacks[x].context)); + callbacks[x].context= libmemcached_malloc(clone, strlen(source->sasl.callbacks[x].context)); - if (cb[x].context == NULL) + if (callbacks[x].context == NULL) { /* Failed to allocate memory, clean up previously allocated memory */ for (size_t y= 0; y < x; ++y) { - libmemcached_free(clone, clone->sasl->callbacks[y].context); + libmemcached_free(clone, clone->sasl.callbacks[y].context); } - libmemcached_free(clone, cb); + libmemcached_free(clone, callbacks); return MEMCACHED_MEMORY_ALLOCATION_FAILURE; } - strcpy(cb[x].context, source->sasl->callbacks[x].context); + strncpy(callbacks[x].context, source->sasl.callbacks[x].context, sizeof(callbacks[x].context)); } else { - sasl_secret_t *src = source->sasl->callbacks[x].context; + sasl_secret_t *src = source->sasl.callbacks[x].context; sasl_secret_t *n = libmemcached_malloc(clone, src->len + 1 + sizeof(*n)); if (n == NULL) { /* Failed to allocate memory, clean up previously allocated memory */ for (size_t y= 0; y < x; ++y) { - libmemcached_free(clone, clone->sasl->callbacks[y].context); + libmemcached_free(clone, clone->sasl.callbacks[y].context); } - libmemcached_free(clone, cb); + libmemcached_free(clone, callbacks); return MEMCACHED_MEMORY_ALLOCATION_FAILURE; } memcpy(n, src, src->len + 1 + sizeof(*n)); - cb[x].context= n; + callbacks[x].context= n; } } - clone->sasl->callbacks= cb; - clone->sasl->is_allocated= true; + clone->sasl.callbacks= callbacks; + clone->sasl.is_allocated= true; return MEMCACHED_SUCCESS; }