-/* 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 <libmemcached/common.h>
+#include <iso646.h>
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)
{
- return ptr->sasl->callbacks;
+ return ptr->sasl.callbacks;
}
/**
* @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
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)
{
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;
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)
{
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);
}
*/
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:
++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;
}