1454
1465
c->write_and_go = conn_closing;
1468
static void init_sasl_conn(conn *c) {
1470
/* should something else be returned? */
1474
if (!c->sasl_conn) {
1475
int result=sasl_server_new("memcached",
1476
NULL, NULL, NULL, NULL,
1477
NULL, 0, &c->sasl_conn);
1478
if (result != SASL_OK) {
1479
if (settings.verbose) {
1480
fprintf(stderr, "Failed to initialize SASL conn.\n");
1482
c->sasl_conn = NULL;
1487
static void bin_list_sasl_mechs(conn *c) {
1488
// Guard against a disabled SASL.
1489
if (!settings.sasl) {
1490
write_bin_error(c, PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND,
1491
c->binary_header.request.bodylen
1492
- c->binary_header.request.keylen);
1497
const char *result_string = NULL;
1498
unsigned int string_length = 0;
1499
int result=sasl_listmech(c->sasl_conn, NULL,
1500
"", /* What to prepend the string with */
1501
" ", /* What to separate mechanisms with */
1502
"", /* What to append to the string */
1503
&result_string, &string_length,
1505
if (result != SASL_OK) {
1506
/* Perhaps there's a better error for this... */
1507
if (settings.verbose) {
1508
fprintf(stderr, "Failed to list SASL mechanisms.\n");
1510
write_bin_error(c, PROTOCOL_BINARY_RESPONSE_AUTH_ERROR, 0);
1513
write_bin_response(c, (char*)result_string, 0, 0, string_length);
1516
static void process_bin_sasl_auth(conn *c) {
1517
// Guard for handling disabled SASL on the server.
1518
if (!settings.sasl) {
1519
write_bin_error(c, PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND,
1520
c->binary_header.request.bodylen
1521
- c->binary_header.request.keylen);
1525
assert(c->binary_header.request.extlen == 0);
1527
int nkey = c->binary_header.request.keylen;
1528
int vlen = c->binary_header.request.bodylen - nkey;
1530
if (nkey > MAX_SASL_MECH_LEN) {
1531
write_bin_error(c, PROTOCOL_BINARY_RESPONSE_EINVAL, vlen);
1532
c->write_and_go = conn_swallow;
1536
char *key = binary_get_key(c);
1539
item *it = item_alloc(key, nkey, 0, 0, vlen);
1542
write_bin_error(c, PROTOCOL_BINARY_RESPONSE_ENOMEM, vlen);
1543
c->write_and_go = conn_swallow;
1548
c->ritem = ITEM_data(it);
1550
conn_set_state(c, conn_nread);
1551
c->substate = bin_reading_sasl_auth_data;
1554
static void process_bin_complete_sasl_auth(conn *c) {
1555
assert(settings.sasl);
1556
const char *out = NULL;
1557
unsigned int outlen = 0;
1562
int nkey = c->binary_header.request.keylen;
1563
int vlen = c->binary_header.request.bodylen - nkey;
1566
memcpy(mech, ITEM_key((item*)c->item), nkey);
1569
if (settings.verbose)
1570
fprintf(stderr, "mech: ``%s'' with %d bytes of data\n", mech, vlen);
1572
const char *challenge = vlen == 0 ? NULL : ITEM_data((item*) c->item);
1577
case PROTOCOL_BINARY_CMD_SASL_AUTH:
1578
result = sasl_server_start(c->sasl_conn, mech,
1582
case PROTOCOL_BINARY_CMD_SASL_STEP:
1583
result = sasl_server_step(c->sasl_conn,
1588
assert(false); /* CMD should be one of the above */
1589
/* This code is pretty much impossible, but makes the compiler
1591
if (settings.verbose) {
1592
fprintf(stderr, "Unhandled command %d with challenge %s\n",
1598
item_unlink(c->item);
1600
if (settings.verbose) {
1601
fprintf(stderr, "sasl result code: %d\n", result);
1606
write_bin_response(c, "Authenticated", 0, 0, strlen("Authenticated"));
1607
pthread_mutex_lock(&c->thread->stats.mutex);
1608
c->thread->stats.auth_cmds++;
1609
pthread_mutex_unlock(&c->thread->stats.mutex);
1612
add_bin_header(c, PROTOCOL_BINARY_RESPONSE_AUTH_CONTINUE, 0, 0, outlen);
1614
add_iov(c, out, outlen);
1616
conn_set_state(c, conn_mwrite);
1617
c->write_and_go = conn_new_cmd;
1620
if (settings.verbose)
1621
fprintf(stderr, "Unknown sasl response: %d\n", result);
1622
write_bin_error(c, PROTOCOL_BINARY_RESPONSE_AUTH_ERROR, 0);
1623
pthread_mutex_lock(&c->thread->stats.mutex);
1624
c->thread->stats.auth_cmds++;
1625
c->thread->stats.auth_errors++;
1626
pthread_mutex_unlock(&c->thread->stats.mutex);
1630
static bool authenticated(conn *c) {
1631
assert(settings.sasl);
1635
case PROTOCOL_BINARY_CMD_SASL_LIST_MECHS: /* FALLTHROUGH */
1636
case PROTOCOL_BINARY_CMD_SASL_AUTH: /* FALLTHROUGH */
1637
case PROTOCOL_BINARY_CMD_SASL_STEP: /* FALLTHROUGH */
1638
case PROTOCOL_BINARY_CMD_VERSION: /* FALLTHROUGH */
1643
const void *uname = NULL;
1644
sasl_getprop(c->sasl_conn, SASL_USERNAME, &uname);
1649
if (settings.verbose > 1) {
1650
fprintf(stderr, "authenticated() in cmd 0x%02x is %s\n",
1651
c->cmd, rv ? "true" : "false");
1457
1657
static void dispatch_bin_command(conn *c) {
1458
1658
int protocol_error = 0;