sasl_conn_t *php_mongo_saslstart(mongo_con_manager *manager, mongo_connection *con, mongo_server_options *options, mongo_server_def *server_def, sasl_conn_t *conn, char **out_payload, int *out_payload_len, int32_t *conversation_id, char **error_message)
{
	const char *raw_payload;
	char encoded_payload[4096];
	unsigned int raw_payload_len, encoded_payload_len;
	int result;
	char *mechanism_list = "GSSAPI";
	const char *mechanism_selected;
	sasl_interact_t *client_interact=NULL;

	result = sasl_client_start(conn, mechanism_list, &client_interact, &raw_payload, &raw_payload_len, &mechanism_selected);
	if (is_sasl_failure(conn, result, error_message)) {
		return NULL;
	}

	if (result != SASL_CONTINUE) {
		*error_message = strdup("Could not negotiate SASL mechanism");
		return NULL;
	}

	mechanism_selected = "GSSAPI";

	result = sasl_encode64(raw_payload, raw_payload_len, encoded_payload, sizeof(encoded_payload), &encoded_payload_len);
	if (is_sasl_failure(conn, result, error_message)) {
		return NULL;
	}

	if (!mongo_connection_authenticate_saslstart(manager, con, options, server_def, (char *)mechanism_selected, encoded_payload, encoded_payload_len + 1, out_payload, out_payload_len, conversation_id, error_message)) {
		return NULL;
	}

	return conn;
}
int php_mongo_io_authenticate_plain(mongo_con_manager *manager, mongo_connection *con, mongo_server_options *options, mongo_server_def *server_def, char **error_message)
{
	char step_payload[4096];
	char *out, *plain;
	char *mechanism = "PLAIN";
	unsigned int step_payload_len, plain_len;
	int outlen;
	int32_t step_conversation_id;
	int result;

	plain_len = spprintf(&plain, 0, "%c%s%c%s", '\0', server_def->username, '\0', server_def->password);

	result = sasl_encode64(plain, plain_len, step_payload, sizeof(step_payload), &step_payload_len);
	if (result != SASL_OK) {
		*error_message = strdup("SASL authentication: Could not base64 encode payload");
		efree(plain);
		return 0;
	}
	efree(plain);

	if (!mongo_connection_authenticate_saslstart(manager, con, options, server_def, mechanism, step_payload, step_payload_len + 1, &out, &outlen, &step_conversation_id, error_message)) {
		return 0;
	}
	free(out);

	return 1;
}
bson_bool_t
_mongoc_sasl_step (mongoc_sasl_t      *sasl,
                   const bson_uint8_t *inbuf,
                   bson_uint32_t       inbuflen,
                   bson_uint8_t       *outbuf,
                   bson_uint32_t       outbufmax,
                   bson_uint32_t      *outbuflen,
                   bson_error_t       *error)
{
   const char *raw = NULL;
   unsigned rawlen = 0;
   int status;

   BSON_ASSERT (sasl);
   BSON_ASSERT (inbuf);
   BSON_ASSERT (outbuf);
   BSON_ASSERT (outbuflen);
   BSON_ASSERT (*outbuflen);

   sasl->step++;

   if (sasl->step == 1) {
      return _mongoc_sasl_start (sasl, outbuf, outbufmax, outbuflen,
                                 error);
   } else if (sasl->step >= 10) {
      bson_set_error (error,
                      MONGOC_ERROR_SASL,
                      SASL_NOTDONE,
                      "SASL Failure: maximum steps detected");
      return FALSE;
   }

   if (!inbuflen) {
      bson_set_error (error,
                      MONGOC_ERROR_SASL,
                      MONGOC_ERROR_CLIENT_AUTHENTICATE,
                      "SASL Failure: no payload provided from server.");
      return FALSE;
   }

   status = sasl_decode64 ((char *)inbuf, inbuflen, (char *)outbuf, outbufmax,
                           outbuflen);
   if (_mongoc_sasl_is_failure (status, error)) {
      return FALSE;
   }

   status = sasl_client_step (sasl->conn, (char *)outbuf, *outbuflen,
                              &sasl->interact, &raw, &rawlen);
   if (_mongoc_sasl_is_failure (status, error)) {
      return FALSE;
   }

   status = sasl_encode64 (raw, rawlen, (char *)outbuf, outbufmax, outbuflen);
   if (_mongoc_sasl_is_failure (status, error)) {
      return FALSE;
   }

   return TRUE;
}
static bool
_mongoc_sasl_start (mongoc_sasl_t      *sasl,
                    uint8_t       *outbuf,
                    uint32_t       outbufmax,
                    uint32_t      *outbuflen,
                    bson_error_t       *error)
{
   const char *service_name = "mongodb";
   const char *service_host = "";
   const char *mechanism = NULL;
   const char *raw = NULL;
   unsigned raw_len = 0;
   int status;

   BSON_ASSERT (sasl);
   BSON_ASSERT (outbuf);
   BSON_ASSERT (outbufmax);
   BSON_ASSERT (outbuflen);

   if (sasl->service_name) {
      service_name = sasl->service_name;
   }

   if (sasl->service_host) {
      service_host = sasl->service_host;
   }

   status = sasl_client_new (service_name, service_host, NULL, NULL,
                             sasl->callbacks, 0, &sasl->conn);
   if (_mongoc_sasl_is_failure (status, error)) {
      return false;
   }

   status = sasl_client_start (sasl->conn, sasl->mechanism,
                               &sasl->interact, &raw, &raw_len,
                               &mechanism);
   if (_mongoc_sasl_is_failure (status, error)) {
      return false;
   }

   if ((0 != strcasecmp (mechanism, "GSSAPI")) &&
       (0 != strcasecmp (mechanism, "PLAIN"))) {
      bson_set_error (error,
                      MONGOC_ERROR_SASL,
                      SASL_NOMECH,
                      "SASL Failure: invalid mechanism \"%s\"",
                      mechanism);
      return false;
   }


   status = sasl_encode64 (raw, raw_len, (char *)outbuf, outbufmax, outbuflen);
   if (_mongoc_sasl_is_failure (status, error)) {
      return false;
   }

   return true;
}
Exemple #5
0
/*
 * encode a string into Base 64
 */
DWORD
VmEncodeToBase64(
    PBYTE       pInput,
    DWORD       dwInputLen,
    PBYTE       *ppBase64Encoded,
    DWORD       *pDwEncodedLen
    )
{
    DWORD   dwError = 0;
    DWORD   dwBase64EncodedBufferLen = 0;
    DWORD   dwBase64EncodedByteLen = 0;
    PBYTE   pBase64Encoded = NULL;

    if (!pInput || !ppBase64Encoded)
    {
        dwError = VM_COMMON_ERROR_INVALID_PARAMETER;
        BAIL_ON_VM_COMMON_ERROR(dwError);
    }

    dwBase64EncodedBufferLen = VM_COMMON_GET_BASE64_ENCODE_LEN(dwInputLen);

    dwError = VmAllocateMemory(dwBase64EncodedBufferLen,
                               (PVOID *)&pBase64Encoded
                               );
    BAIL_ON_VM_COMMON_ERROR(dwError);

    dwError = sasl_encode64((PCSTR)pInput,
                            dwInputLen,
                            (PSTR)pBase64Encoded,
                            dwBase64EncodedBufferLen,
                            &dwBase64EncodedByteLen
                            );
    BAIL_ON_VM_COMMON_ERROR(dwError);

    *ppBase64Encoded = pBase64Encoded;
    *pDwEncodedLen = dwBase64EncodedByteLen;

cleanup:
    return dwError;

error:
    VM_COMMON_SAFE_FREE_MEMORY(pBase64Encoded);
    if (ppBase64Encoded)
    {
        *ppBase64Encoded = NULL;
    }
    if (pDwEncodedLen)
    {
        *pDwEncodedLen = 0;
    }
    goto cleanup;
}
int php_mongo_saslcontinue(mongo_con_manager *manager, mongo_connection *con, mongo_server_options *options, mongo_server_def *server_def, sasl_conn_t *conn, char *step_payload, int step_payload_len, int32_t conversation_id, char **error_message) {
	sasl_interact_t *client_interact=NULL;

	/*
	 * Snippet from sasl.h:
	 *  4. client calls sasl_client_step()
	 *  4b. If SASL error, goto 7 or 3
	 *  4c. If SASL_OK, continue or goto 6 if last server response was success
	 */

	do {
		char base_payload[4096], payload[4096];
		unsigned int base_payload_len, payload_len;
		const char *out;
		unsigned int outlen;
		unsigned char done = 0;
		int result;

		step_payload_len--; /* Remove the \0 from the string */
		result = sasl_decode64(step_payload, step_payload_len, base_payload, sizeof(base_payload), &base_payload_len);
		if (is_sasl_failure(conn, result, error_message)) {
			return 0;
		}

		result = sasl_client_step(conn, (const char *)base_payload, base_payload_len, &client_interact, &out, &outlen);
		if (is_sasl_failure(conn, result, error_message)) {
			return 0;
		}

		result = sasl_encode64(out, outlen, payload, sizeof(base_payload), &payload_len);
		if (is_sasl_failure(conn, result, error_message)) {
			return 0;
		}

		if (!mongo_connection_authenticate_saslcontinue(manager, con, options, server_def, conversation_id, payload, payload_len + 1, &step_payload, &step_payload_len, &done, error_message)) {
			return 0;
		}

		if (done) {
			break;
		}
	} while (1);

	return 1;
}
Exemple #7
0
/* b64data = cyrussasl.encode64(data)
 *
 * A convenience method to use the Cyrus SASL library implementation of base64
 * encoding data. Takes, and returns, a Lua string object. Since Lua strings 
 * may contain true 8-bit data (including '\0'), the length of the data is 
 * obtained by examining the length of the string.
 */
static int cyrussasl_sasl_encode64(lua_State *l)
{
  unsigned len_out;
  int alloclen;
  char *buf = NULL;
  const char *data = NULL;
  size_t len;
  int err;

  int numargs = lua_gettop(l);
  if (numargs != 1) {
    lua_pushstring(l, "usage: b64data = cyrussasl.encode64(data)");
    lua_error(l);
    return 0;
  }

  len = 0;
  data = tolstring(l, 1, &len);

  /* Allocate a new buffer that will accommodate the data in its most-possibly-
   * expanded state. */
  alloclen = ((len / 3) + 1) * 4 + 1;
  buf = malloc(alloclen);
  if (!buf) {
    lua_pushstring(l, "malloc failed");
    lua_error(l);
    return 0;
  }

  err = sasl_encode64(data, len, buf, alloclen, &len_out);
  if ( err != SASL_OK ) {
    free(buf);
    lua_pushstring(l, "sasl_encode64 failed");
    lua_error(l);
    return 0;
  }

  lua_pushlstring(l, buf, len_out);
  free(buf);
  return 1;
}
static int xsasl_cyrus_server_auth_response(int sasl_status,
					            SERVEROUT_TYPE serverout,
					            unsigned serveroutlen,
					            VSTRING *reply)
{
    const char *myname = "xsasl_cyrus_server_auth_response";
    unsigned enc_length;
    unsigned enc_length_out;

    /*
     * Encode the server first/next non-error response; otherwise return the
     * unencoded error text that corresponds to the SASL error status.
     * 
     * Regarding the hairy expression below: output from sasl_encode64() comes
     * in multiples of four bytes for each triple of input bytes, plus four
     * bytes for any incomplete last triple, plus one byte for the null
     * terminator.
     */
    if (sasl_status == SASL_OK) {
	vstring_strcpy(reply, "");
	return (XSASL_AUTH_DONE);
    } else if (sasl_status == SASL_CONTINUE) {
	if (msg_verbose)
	    msg_info("%s: uncoded server challenge: %.*s",
		     myname, (int) serveroutlen, serverout);
	enc_length = ((serveroutlen + 2) / 3) * 4 + 1;
	VSTRING_RESET(reply);			/* Fix 200512 */
	VSTRING_SPACE(reply, enc_length);
	if ((sasl_status = sasl_encode64(serverout, serveroutlen,
					 STR(reply), vstring_avail(reply),
					 &enc_length_out)) != SASL_OK)
	    msg_panic("%s: sasl_encode64 botch: %s",
		      myname, xsasl_cyrus_strerror(sasl_status));
	return (XSASL_AUTH_MORE);
    } else {
	if (sasl_status == SASL_NOUSER)		/* privacy */
	    sasl_status = SASL_BADAUTH;
	vstring_strcpy(reply, xsasl_cyrus_strerror(sasl_status));
	return (XSASL_AUTH_FAIL);
    }
}
int php_mongo_saslcontinue(mongo_con_manager *manager, mongo_connection *con, mongo_server_options *options, mongo_server_def *server_def, sasl_conn_t *conn, char *step_payload, int step_payload_len, int32_t conversation_id, char **error_message) {
	int result;
	sasl_interact_t *client_interact=NULL;

	do {
		char base_payload[4096], payload[4096];
		unsigned int base_payload_len, payload_len;
		unsigned char done;
		const char *out;
		unsigned int outlen;

		result = sasl_decode64(step_payload, step_payload_len, base_payload, sizeof(base_payload), &base_payload_len);
		if (is_sasl_failure(conn, result, error_message)) {
			return result;
		}

		result = sasl_client_step(conn, (const char *)base_payload, base_payload_len, &client_interact, &out, &outlen);
		if (is_sasl_failure(conn, result, error_message)) {
			return result;
		}

		/* TODO : Deal with interaction */

		if (result == SASL_OK) {
			/* We are all done */
			break;
		}

		result = sasl_encode64(out, outlen, payload, sizeof(base_payload), &payload_len);
		if (is_sasl_failure(conn, result, error_message)) {
			return result;
		}

		if (!mongo_connection_authenticate_saslcontinue(manager, con, options, server_def, conversation_id, payload, payload_len + 1, &step_payload, &step_payload_len, &done, (char **)&error_message)) {
			*error_message = strdup("saslStart failed miserably");
			return result;
		}
	} while (result == SASL_INTERACT || result == SASL_CONTINUE);

	return result;
}
Exemple #10
0
/* NOTE: success_data will need to be free()d by the caller */
int saslserver(sasl_conn_t *conn, const char *mech,
	       const char *init_resp, const char *resp_prefix,
	       const char *continuation, const char *empty_chal,
               struct protstream *pin, struct protstream *pout,
	       int *sasl_result, char **success_data)
{
    char base64[BASE64_BUF_SIZE+1];
    char *clientin = NULL;
    unsigned int clientinlen = 0;
    const char *serverout = NULL;
    unsigned int serveroutlen = 0;
    int r = SASL_OK;

    if (success_data) *success_data = NULL;

    /* initial response */
    if (init_resp) {
	clientin = base64;
	if (!strcmp(init_resp, "=")) {
	    /* zero-length initial response */
	    base64[0] = '\0';
	}
	else {
	    r = sasl_decode64(init_resp, strlen(init_resp),
			      clientin, BASE64_BUF_SIZE, &clientinlen);
	}
    }

    /* start the exchange */
    if (r == SASL_OK)
	r = sasl_server_start(conn, mech, clientin, clientinlen,
			      &serverout, &serveroutlen);

    while (r == SASL_CONTINUE) {
	char *p;

	/* send the challenge to the client */
	if (serveroutlen) {
	    r = sasl_encode64(serverout, serveroutlen,
			      base64, BASE64_BUF_SIZE, NULL);
	    if (r != SASL_OK) break;
	    serverout = base64;
	}
	else {
	    serverout = empty_chal;
	}

	prot_printf(pout, "%s%s\r\n", continuation, serverout);
	prot_flush(pout);

	/* get response from the client */
	if (!prot_fgets(base64, BASE64_BUF_SIZE, pin) ||
	    strncasecmp(base64, resp_prefix, strlen(resp_prefix))) {
	    if (sasl_result) *sasl_result = SASL_FAIL;
	    return IMAP_SASL_PROTERR;
	}

	/* trim CRLF */
	p = base64 + strlen(base64) - 1;
	if (p >= base64 && *p == '\n') *p-- = '\0';
	if (p >= base64 && *p == '\r') *p-- = '\0';

	/* trim prefix */
	p = base64 + strlen(resp_prefix);

	/* check if client cancelled */
	if (p[0] == '*') {
	    if(sasl_result) *sasl_result = SASL_BADPROT;
	    return IMAP_SASL_CANCEL;
	}

	/* decode the response */
	clientin = base64;
	r = sasl_decode64(p, strlen(p),
			  clientin, BASE64_BUF_SIZE, &clientinlen);
	if (r != SASL_OK) break;

	/* do the next step */
	r = sasl_server_step(conn, clientin, clientinlen,
			     &serverout, &serveroutlen);
    }

    /* success data */
    if (r == SASL_OK && serverout && success_data) {
	r = sasl_encode64(serverout, serveroutlen,
			  base64, BASE64_BUF_SIZE, NULL);
	if (r == SASL_OK)
	    *success_data = (char *) xstrdup(base64);
    }

    if (sasl_result) *sasl_result = r;
    return (r == SASL_OK ? 0 : IMAP_SASL_FAIL);
}
Exemple #11
0
/**
 * Send connections to nuauth: between 1 and #CONN_MAX connections
 * in a big packet of format:
 *   [ nu_header + nu_authfield_ipv6 * N ]
 */
int send_user_pckt(nuauth_session_t * session, conn_t * carray[CONN_MAX])
{
	char data[PACKET_SIZE];
	char *pointer;
	unsigned int item;
	struct nu_header *header;
	struct nu_authreq *authreq;
	struct nu_authfield_ipv6 *authfield;
	struct nu_authfield_app *appfield;
	unsigned len;
	const char *appname;
	char *app_ptr;

	session->timestamp_last_sent = time(NULL);
	memset(data, 0, sizeof data);

	header = (struct nu_header *) data;
	header->proto = PROTO_VERSION;
	header->msg_type = USER_REQUEST;
	header->option = 0;
	header->length = sizeof(struct nu_header);
	pointer = (char *) (header + 1);

	for (item = 0; ((item < CONN_MAX) && carray[item] != NULL); item++) {
#if DEBUG
		printf("adding one authreq\n");
#endif
#ifdef LINUX
		/* get application name from inode */
		appname = prg_cache_get(carray[item]->inode);
#else
		appname = "UNKNOWN";
#endif
		header->length +=
		    sizeof(struct nu_authreq) +
		    sizeof(struct nu_authfield_ipv6);

		authreq = (struct nu_authreq *) pointer;
		authreq->packet_seq = session->packet_seq++;
		authreq->packet_length =
		    sizeof(struct nu_authreq) +
		    sizeof(struct nu_authfield_ipv6);

		authfield = (struct nu_authfield_ipv6 *) (authreq + 1);
		authfield->type = IPV6_FIELD;
		authfield->option = 0;
		authfield->src = carray[item]->ip_src;
		authfield->dst = carray[item]->ip_dst;
		authfield->proto = carray[item]->protocol;
		authfield->flags = 0;
		authfield->FUSE = 0;
#ifdef _I386__ENDIAN_H_
#ifdef __DARWIN_LITTLE_ENDIAN
		authfield->sport = carray[item]->port_src;
		authfield->dport = carray[item]->port_dst;
#else
		authfield->sport = htons(carray[item]->port_src);
		authfield->dport = htons(carray[item]->port_dst);
#endif				/* DARWIN LITTLE ENDIAN */
#else
		authfield->sport = htons(carray[item]->port_src);
		authfield->dport = htons(carray[item]->port_dst);
#endif				/* I386 ENDIAN */

		/* application field  */
		appfield = (struct nu_authfield_app *) (authfield + 1);
		appfield->type = APP_FIELD;
		appfield->option = APP_TYPE_NAME;
		app_ptr = (char *) (appfield + 1);
		sasl_encode64(appname, strlen(appname), app_ptr,
			      PROGNAME_BASE64_WIDTH, &len);
		appfield->length = sizeof(struct nu_authfield_app) + len;
		authreq->packet_length += appfield->length;

		/* glue piece together on data if packet is not too long */
		header->length += appfield->length;

		if (session->hash) {
			struct nu_authfield_app *sigfield;
			const char *appsig;
			appsig = prg_cache_getsig(session->hash, carray[item]->inode);
			sigfield = (struct nu_authfield_app *) ((char*)appfield + appfield->length);
			sigfield->type = HASH_FIELD;
			sigfield->option = 0;
			app_ptr = (char *) (sigfield + 1);
			memcpy(app_ptr, appsig, strlen(appsig));
			sigfield->length = sizeof(struct nu_authfield_app) + strlen(appsig);

			authreq->packet_length += sigfield->length;

			/* glue piece together on data if packet is not too long */
			header->length += sigfield->length;
			sigfield->length = htons(sigfield->length);
		}

		assert(header->length < PACKET_SIZE);

		pointer += authreq->packet_length;

		appfield->length = htons(appfield->length);

		authreq->packet_length = htons(authreq->packet_length);
		authfield->length =
		    htons(sizeof(struct nu_authfield_ipv6));
	}
	header->length = htons(header->length);
	if (session->debug_mode) {
		log_printf(DEBUG_LEVEL_INFO, "[+] Send %u new connection(s) to nuauth\n", item);
	}

	/* and send it */
#if XXX
	if (session->tls) {
		if (gnutls_record_send
		    (session->tls, data, pointer - data) <= 0) {
			log_printf(DEBUG_LEVEL_CRITICAL, "write failed\n");
			return 0;
		}
	}
#else
	if (ufwissl_write(session->ufwissl, (char*)data, pointer - data) < 0)
	{
		log_printf(DEBUG_LEVEL_CRITICAL, "write failed\n");
		return 0;
	}
#endif
	return 1;
}
static int xsasl_cyrus_client_next(XSASL_CLIENT *xp, const char *server_reply,
				           VSTRING *client_reply)
{
    const char *myname = "xsasl_cyrus_client_next";
    XSASL_CYRUS_CLIENT *client = (XSASL_CYRUS_CLIENT *) xp;
    unsigned enc_length;
    unsigned enc_length_out;
    CLIENTOUT_TYPE clientout;
    unsigned clientoutlen;
    unsigned serverinlen;
    int     sasl_status;

    /*
     * Process a server challenge.
     */
    serverinlen = strlen(server_reply);
    VSTRING_RESET(client->decoded);		/* Fix 200512 */
    VSTRING_SPACE(client->decoded, serverinlen);
    if ((sasl_status = SASL_DECODE64(server_reply, serverinlen,
				     STR(client->decoded),
				     vstring_avail(client->decoded),
				     &enc_length)) != SASL_OK) {
	vstring_strcpy(client_reply, xsasl_cyrus_strerror(sasl_status));
	return (XSASL_AUTH_FORM);
    }
    if (msg_verbose)
	msg_info("%s: decoded challenge: %.*s",
		 myname, (int) enc_length, STR(client->decoded));
    sasl_status = sasl_client_step(client->sasl_conn, STR(client->decoded),
				   enc_length, NO_SASL_INTERACTION,
				   &clientout, &clientoutlen);
    if (sasl_status != SASL_OK && sasl_status != SASL_CONTINUE) {
	vstring_strcpy(client_reply, xsasl_cyrus_strerror(sasl_status));
	return (XSASL_AUTH_FAIL);
    }

    /*
     * Send a client response.
     */
    if (clientoutlen > 0) {
	if (msg_verbose)
	    msg_info("%s: uncoded client response %.*s",
		     myname, (int) clientoutlen, clientout);
	enc_length = ENCODE64_LENGTH(clientoutlen) + 1;
	VSTRING_RESET(client_reply);		/* Fix 200512 */
	VSTRING_SPACE(client_reply, enc_length);
	if ((sasl_status = sasl_encode64(clientout, clientoutlen,
					 STR(client_reply),
					 vstring_avail(client_reply),
					 &enc_length_out)) != SASL_OK)
	    msg_panic("%s: sasl_encode64 botch: %s",
		      myname, xsasl_cyrus_strerror(sasl_status));
#if SASL_VERSION_MAJOR < 2
	/* SASL version 1 doesn't free memory that it allocates. */
	free(clientout);
#endif
    } else {
	/* XXX Can't happen. */
	vstring_strcpy(client_reply, "");
    }
    return (XSASL_AUTH_OK);
}
static int xsasl_cyrus_client_first(XSASL_CLIENT *xp,
				            const char *mechanism_list,
				            const char *username,
				            const char *password,
				            const char **mechanism,
				            VSTRING *init_resp)
{
    const char *myname = "xsasl_cyrus_client_first";
    XSASL_CYRUS_CLIENT *client = (XSASL_CYRUS_CLIENT *) xp;
    unsigned enc_length;
    unsigned enc_length_out;
    CLIENTOUT_TYPE clientout;
    unsigned clientoutlen;
    int     sasl_status;

#define NO_SASL_SECRET		0
#define NO_SASL_INTERACTION	0

    /*
     * Save the username and password for the call-backs.
     */
    if (client->username)
	myfree(client->username);
    client->username = mystrdup(username);
    if (client->password)
	myfree(client->password);
    client->password = mystrdup(password);

    /*
     * Start the client side authentication protocol.
     */
    sasl_status = SASL_CLIENT_START((sasl_conn_t *) client->sasl_conn,
				    mechanism_list,
				    NO_SASL_SECRET, NO_SASL_INTERACTION,
				    &clientout, &clientoutlen, mechanism);
    if (sasl_status != SASL_OK && sasl_status != SASL_CONTINUE) {
	vstring_strcpy(init_resp, xsasl_cyrus_strerror(sasl_status));
	return (XSASL_AUTH_FAIL);
    }

    /*
     * Generate the AUTH command and the optional initial client response.
     * sasl_encode64() produces four bytes for each complete or incomplete
     * triple of input bytes. Allocate an extra byte for string termination.
     */
#define ENCODE64_LENGTH(n)	((((n) + 2) / 3) * 4)

    if (clientoutlen > 0) {
	if (msg_verbose) {
	    escape(client->decoded, clientout, clientoutlen);
	    msg_info("%s: uncoded initial reply: %s",
		     myname, STR(client->decoded));
	}
	enc_length = ENCODE64_LENGTH(clientoutlen) + 1;
	VSTRING_RESET(init_resp);		/* Fix 200512 */
	VSTRING_SPACE(init_resp, enc_length);
	if ((sasl_status = sasl_encode64(clientout, clientoutlen,
					 STR(init_resp),
					 vstring_avail(init_resp),
					 &enc_length_out)) != SASL_OK)
	    msg_panic("%s: sasl_encode64 botch: %s",
		      myname, xsasl_cyrus_strerror(sasl_status));
	VSTRING_AT_OFFSET(init_resp, enc_length_out);	/* XXX */
#if SASL_VERSION_MAJOR < 2
	/* SASL version 1 doesn't free memory that it allocates. */
	free(clientout);
#endif
    } else {
	vstring_strcpy(init_resp, "");
    }
    return (XSASL_AUTH_OK);
}
Exemple #14
0
krb5_error_code
srp_make_enc_keyblock(
    srp_gss_ctx_id_t srp_context_handle)
{
    char *srp_session_key_str = NULL;
    unsigned char *hmac_key = NULL;
    int b64_alloc_len = 0;

    unsigned char *ptr_expanded_key = NULL;
    unsigned char expanded_session_key[SRP_EXPAND_KEY_LEN] = {0};

    unsigned char srp_session_key[SRP_EXPAND_SESSION_KEY_LEN] = {0};
    int srp_session_key_len = sizeof(srp_session_key);

    unsigned char iv_data[AES_BLOCK_SIZE] = {0};
    int iv_data_len = sizeof(iv_data);

    int b64_session_key_len = 0;
    krb5_error_code krb5_err = KRB5_BAD_ENCTYPE;

    if (!srp_context_handle->srp_session_key ||
        srp_context_handle->srp_session_key_len == 0)
    {
        krb5_err = GSS_S_DEFECTIVE_TOKEN;
        goto error;
    }

    srp_print_hex(srp_context_handle->srp_session_key,
                  srp_context_handle->srp_session_key_len,
                  "srp_make_enc_keyblock: SRP-negotiated session key ");

    /* Expand SRP session key to obtain more bytes for IV/session key */
    krb5_err = srp_expand_session_key(
                   srp_context_handle->srp_session_key,
                   srp_context_handle->srp_session_key_len,
                   srp_context_handle->upn_name,         /* salt */
                   (int) strlen(srp_context_handle->upn_name), /* salt length */
                   SRP_EXPAND_KEY_ITER,
                   sizeof(expanded_session_key),
                   expanded_session_key);
    if (krb5_err)
    {
        goto error;
    }

    /* Carve up parts of the expanded key for various purposes */
    ptr_expanded_key = expanded_session_key;

    /* Initialization vector */
    memcpy(iv_data, ptr_expanded_key, iv_data_len);
    ptr_expanded_key += iv_data_len;

    srp_print_hex(iv_data,
                  iv_data_len,
                  "srp_make_enc_keyblock: got initialization vector ");

    /* SRP "derived session" key */
    memcpy(srp_session_key, ptr_expanded_key, srp_session_key_len);
    ptr_expanded_key += sizeof(srp_session_key);

    /* HMAC key, remaining 16 bytes */
    hmac_key = ptr_expanded_key;

    srp_print_hex(srp_session_key,
                  srp_session_key_len,
                  "srp_make_enc_keyblock: got derived session key");

    /* Build b64 encoded string of SRP session key */
    b64_alloc_len = (srp_session_key_len + 2) / 3  * 4 + 1;
    srp_session_key_str = calloc(b64_alloc_len, sizeof(char));
    if (!srp_session_key_str)
    {
        krb5_err = ENOMEM;
        goto error;
    }

    krb5_err = sasl_encode64(
                   srp_session_key,
                   srp_session_key_len,
                   srp_session_key_str,
                   b64_alloc_len,
                   &b64_session_key_len);
    if (krb5_err)
    {
        krb5_err = ENOMEM;
        goto error;
    }
    srp_session_key_str[b64_session_key_len] = '\0';

    srp_context_handle->keyblock = calloc(1, sizeof(krb5_keyblock));
    if (!srp_context_handle->keyblock)
    {
        krb5_err = ENOMEM;
        goto error;
    }

    /* Generate encryption key from SRP shared key */
    krb5_err = srp_gen_keyblock(
                   srp_context_handle->krb5_ctx,
                   SRP_ENC_KEYTYPE,
                   srp_session_key_str,
                   srp_context_handle->upn_name,
                   srp_context_handle->keyblock);
    if (krb5_err)
    {
        goto error;
    }

    srp_print_hex(srp_context_handle->keyblock->contents,
                  srp_context_handle->keyblock->length,
                  "srp_make_enc_keyblock: keyblock value");

     memset(srp_context_handle->aes_encrypt_iv, 0, iv_data_len);
     memcpy(srp_context_handle->aes_encrypt_iv, iv_data, iv_data_len);

     memset(srp_context_handle->aes_decrypt_iv, 0, iv_data_len);
     memcpy(srp_context_handle->aes_decrypt_iv, iv_data, iv_data_len);

    AES_set_encrypt_key(
        srp_context_handle->keyblock->contents,
        srp_context_handle->keyblock->length * 8,
        &srp_context_handle->aes_encrypt_key);
    AES_set_decrypt_key(
        srp_context_handle->keyblock->contents,
        srp_context_handle->keyblock->length * 8,
        &srp_context_handle->aes_decrypt_key);

    if (srp_init_hmac(&srp_context_handle->hmac_ctx,
                      hmac_key,
                      SRP_EXPAND_HMAC_KEY))
    {
        krb5_err = ENOMEM;
        goto error;
    }

error:
    if (krb5_err)
    {
        if (srp_context_handle->keyblock)
        {
            free(srp_context_handle->keyblock);
        }
    }

    if (srp_session_key_str)
    {
        free(srp_session_key_str);
    }
    return krb5_err;
}
Exemple #15
0
int auth_sasl(char *mechlist, isieve_t *obj, const char **mechusing,
	      sasl_ssf_t *ssf, char **errstr)
{
  sasl_interact_t *client_interact=NULL;
  int saslresult=SASL_INTERACT;
  const char *out;
  unsigned int outlen;
  char *in;
  unsigned int inlen;
  char inbase64[2048];
  unsigned int inbase64len;

  imt_stat status = STAT_CONT;

  if(!mechlist || !obj || !mechusing) return -1;

  /* call sasl client start */
  while (saslresult==SASL_INTERACT)
  {
    saslresult=sasl_client_start(obj->conn, mechlist,
				 &client_interact,
				 &out, &outlen,
				 mechusing);
    if (saslresult==SASL_INTERACT)
      fillin_interactions(client_interact); /* fill in prompts */      
  }

  if ((saslresult!=SASL_OK) && (saslresult!=SASL_CONTINUE)) return saslresult;

  if (out!=NULL)
  {
    prot_printf(obj->pout,"AUTHENTICATE \"%s\" ",*mechusing);

    sasl_encode64(out, outlen,
		  inbase64, sizeof(inbase64), &inbase64len);

    prot_printf(obj->pout, "{%d+}\r\n",inbase64len);
    prot_write(obj->pout,inbase64,inbase64len);
    prot_printf(obj->pout,"\r\n");
  } else {
    prot_printf(obj->pout,"AUTHENTICATE \"%s\"\r\n",*mechusing);
  }
  prot_flush(obj->pout);

  inlen = 0;

  /* get reply */
  status=getauthline(obj,&in,&inlen, errstr);

  while (status==STAT_CONT)
  {
    saslresult=SASL_INTERACT;
    while (saslresult==SASL_INTERACT)
    {
      saslresult=sasl_client_step(obj->conn,
				  in,
				  inlen,
				  &client_interact,
				  &out,&outlen);

      if (saslresult==SASL_INTERACT)
	fillin_interactions(client_interact); /* fill in prompts */
    }

    /* check if sasl suceeded */
    if (saslresult<SASL_OK)
    {
	/* send cancel notice */
	prot_printf(obj->pout, "*\r\n");
	prot_flush(obj->pout);

	/* eat the auth line that confirms that we canceled */
	if(getauthline(obj,&in,&inlen,errstr) != STAT_NO) {
	    *errstr = xstrdup("protocol error");
	} else {
	    *errstr = xstrdup(sasl_errstring(saslresult,NULL,NULL));
	}
	
	return saslresult;
    }

    /* send to server */

    sasl_encode64(out, outlen,
		  inbase64, sizeof(inbase64), &inbase64len);

    prot_printf(obj->pout, "{%d+}\r\n",inbase64len);
    prot_flush(obj->pout);
    prot_write(obj->pout,inbase64,inbase64len);
    prot_flush(obj->pout);
    prot_printf(obj->pout,"\r\n");
    prot_flush(obj->pout);

    /* get reply */
    status=getauthline(obj,&in,&inlen, errstr);
  }

  if(status == STAT_OK) {
      /* do we have a last send? */
      if(in) {
	  saslresult=sasl_client_step(obj->conn,
				      in,
				      inlen,
				      &client_interact,
				      &out, &outlen);
	  
	  if(saslresult != SASL_OK)
	      return -1;
      }

      if (ssf) {
	  const void *ssfp;

	  saslresult = sasl_getprop(obj->conn, SASL_SSF, &ssfp);
	  if(saslresult != SASL_OK) return -1;

	  *ssf = *((sasl_ssf_t *) ssfp);
      }

      /* turn on layer if need be */
      prot_setsasl(obj->pin,  obj->conn);
      prot_setsasl(obj->pout, obj->conn);

      /* There wasn't a last send, or we are already OK */
      return 0;
  } else {
      /* Error */
      return -1;
  }
}
Exemple #16
0
bool
_mongoc_cyrus_step (mongoc_cyrus_t *sasl,
                    const uint8_t *inbuf,
                    uint32_t inbuflen,
                    uint8_t *outbuf,
                    uint32_t outbufmax,
                    uint32_t *outbuflen,
                    bson_error_t *error)
{
   const char *raw = NULL;
   unsigned rawlen = 0;
   int status;

   BSON_ASSERT (sasl);
   BSON_ASSERT (inbuf);
   BSON_ASSERT (outbuf);
   BSON_ASSERT (outbuflen);

   TRACE ("Running %d, inbuflen: %" PRIu32, sasl->step, inbuflen);
   sasl->step++;

   if (sasl->step == 1) {
      return _mongoc_cyrus_start (sasl, outbuf, outbufmax, outbuflen, error);
   } else if (sasl->step >= 10) {
      bson_set_error (error,
                      MONGOC_ERROR_SASL,
                      SASL_NOTDONE,
                      "SASL Failure: maximum steps detected");
      return false;
   }

   TRACE ("Running %d, inbuflen: %" PRIu32, sasl->step, inbuflen);
   if (!inbuflen) {
      bson_set_error (error,
                      MONGOC_ERROR_SASL,
                      MONGOC_ERROR_CLIENT_AUTHENTICATE,
                      "SASL Failure: no payload provided from server: %s",
                      sasl_errdetail (sasl->conn));
      return false;
   }

   status = sasl_decode64 (
      (char *) inbuf, inbuflen, (char *) outbuf, outbufmax, outbuflen);
   if (_mongoc_cyrus_is_failure (status, error)) {
      return false;
   }

   TRACE ("%s", "Running client_step");
   status = sasl_client_step (
      sasl->conn, (char *) outbuf, *outbuflen, &sasl->interact, &raw, &rawlen);
   TRACE ("%s sent a client step",
          status == SASL_OK ? "Successfully" : "UNSUCCESSFULLY");
   if (_mongoc_cyrus_is_failure (status, error)) {
      return false;
   }

   status = sasl_encode64 (raw, rawlen, (char *) outbuf, outbufmax, outbuflen);
   if (_mongoc_cyrus_is_failure (status, error)) {
      return false;
   }

   return true;
}
Exemple #17
0
int mailesmtp_auth_sasl(mailsmtp * session, const char * auth_type,
    const char * server_fqdn,
    const char * local_ip_port,
    const char * remote_ip_port,
    const char * login, const char * auth_name,
    const char * password, const char * realm)
{
#ifdef USE_SASL
  int r;
  char command[SMTP_STRING_SIZE];
  sasl_callback_t sasl_callback[5];
  const char * sasl_out;
  unsigned sasl_out_len;
  const char * mechusing;
  sasl_secret_t * secret;
  int res;
  size_t len;
  char * encoded;
  unsigned int encoded_len;
  unsigned int max_encoded;

  sasl_callback[0].id = SASL_CB_GETREALM;
  sasl_callback[0].proc =  (int (*)(void)) sasl_getrealm;
  sasl_callback[0].context = session;
  sasl_callback[1].id = SASL_CB_USER;
  sasl_callback[1].proc =  (int (*)(void)) sasl_getsimple;
  sasl_callback[1].context = session;
  sasl_callback[2].id = SASL_CB_AUTHNAME;
  sasl_callback[2].proc =  (int (*)(void)) sasl_getsimple;
  sasl_callback[2].context = session;
  sasl_callback[3].id = SASL_CB_PASS;
  sasl_callback[3].proc =  (int (*)(void)) sasl_getsecret;
  sasl_callback[3].context = session;
  sasl_callback[4].id = SASL_CB_LIST_END;
  sasl_callback[4].proc =  NULL;
  sasl_callback[4].context = NULL;

  len = strlen(password);
  secret = malloc(sizeof(* secret) + len);
  if (secret == NULL) {
    res = MAILSMTP_ERROR_MEMORY;
    goto err;
  }
  secret->len = len;
  memcpy(secret->data, password, len + 1);

  session->smtp_sasl.sasl_server_fqdn = server_fqdn;
  session->smtp_sasl.sasl_login = login;
  session->smtp_sasl.sasl_auth_name = auth_name;
  session->smtp_sasl.sasl_password = password;
  session->smtp_sasl.sasl_realm = realm;
  session->smtp_sasl.sasl_secret = secret;

  /* init SASL */
  if (session->smtp_sasl.sasl_conn != NULL) {
    sasl_dispose((sasl_conn_t **) &session->smtp_sasl.sasl_conn);
    session->smtp_sasl.sasl_conn = NULL;
  }
  else {
    mailsasl_ref();
  }

  r = sasl_client_new("smtp", server_fqdn,
      local_ip_port, remote_ip_port, sasl_callback, 0,
      (sasl_conn_t **) &session->smtp_sasl.sasl_conn);
  if (r != SASL_OK) {
    res = MAILSMTP_ERROR_AUTH_LOGIN;
    goto free_secret;
  }

  r = sasl_client_start(session->smtp_sasl.sasl_conn,
      auth_type, NULL, &sasl_out, &sasl_out_len, &mechusing);
  if ((r != SASL_CONTINUE) && (r != SASL_OK)) {
    res = MAILSMTP_ERROR_AUTH_LOGIN;
    goto free_sasl_conn;
  }

  if (sasl_out_len != 0) {
    max_encoded = ((sasl_out_len + 2) / 3) * 4;
    encoded = malloc(max_encoded + 1);
    if (encoded == NULL) {
      res = MAILSMTP_ERROR_MEMORY;
      goto free_sasl_conn;
    }

    r = sasl_encode64(sasl_out, sasl_out_len,
        encoded, max_encoded + 1, &encoded_len);
    if (r != SASL_OK) {
      free(encoded);
      res = MAILSMTP_ERROR_MEMORY;
      goto free_sasl_conn;
    }

    snprintf(command, SMTP_STRING_SIZE, "AUTH %s %s\r\n", auth_type, encoded);

    free(encoded);
  }
  else {
    snprintf(command, SMTP_STRING_SIZE, "AUTH %s\r\n", auth_type);
  }

  r = send_command_private(session, command, 0);
  if (r == -1) {
    res = MAILSMTP_ERROR_STREAM;
    goto free_sasl_conn;
  }

  while (1) {
    r = read_response(session);
    switch (r) {
    case 220:
    case 235:
      res = MAILSMTP_NO_ERROR;
      goto free_sasl_conn;

    case 535:
      res = MAILSMTP_ERROR_AUTH_LOGIN;
      goto free_sasl_conn;

    case 553:
    case 554:
      res = MAILSMTP_ERROR_AUTH_AUTHENTICATION_FAILED;
      goto free_sasl_conn;

    case 334:
      {
        size_t response_len;
        char * decoded;
        unsigned int decoded_len;
        unsigned int max_decoded;
        char * p;

        p = strchr(session->response, '\r');
        if (p != NULL) {
          * p = '\0';
        }
        p = strchr(session->response, '\n');
        if (p != NULL) {
          * p = '\0';
        }

        response_len = strlen(session->response);
        max_decoded = response_len * 3 / 4;
        decoded = malloc(max_decoded + 1);
        if (decoded == NULL) {
          res = MAILSMTP_ERROR_MEMORY;
          goto free_sasl_conn;
        }

        r = sasl_decode64(session->response, response_len,
            decoded, max_decoded + 1, &decoded_len);

        if (r != SASL_OK) {
          free(decoded);
          res = MAILSMTP_ERROR_MEMORY;
          goto free_sasl_conn;
        }

        r = sasl_client_step(session->smtp_sasl.sasl_conn,
            decoded, decoded_len, NULL, &sasl_out, &sasl_out_len);

        free(decoded);

        if ((r != SASL_CONTINUE) && (r != SASL_OK)) {
          res = MAILSMTP_ERROR_AUTH_LOGIN;
          goto free_sasl_conn;
        }

        max_encoded = ((sasl_out_len + 2) / 3) * 4;
        encoded = malloc(max_encoded + 1);
        if (encoded == NULL) {
          res = MAILSMTP_ERROR_MEMORY;
          goto free_sasl_conn;
        }

        r = sasl_encode64(sasl_out, sasl_out_len,
            encoded, max_encoded + 1, &encoded_len);
        if (r != SASL_OK) {
          free(encoded);
          res = MAILSMTP_ERROR_MEMORY;
          goto free_sasl_conn;
        }

        snprintf(command, SMTP_STRING_SIZE, "%s\r\n", encoded);
        r = send_command(session, command);

        free(encoded);

        if (r == -1) {
          res = MAILSMTP_ERROR_STREAM;
          goto free_sasl_conn;
        }
      }
      break;

    default:
      res = auth_map_errors(r);
      goto free_sasl_conn;
    }
  }

  res = MAILSMTP_NO_ERROR;

 free_sasl_conn:
  sasl_dispose((sasl_conn_t **) &session->smtp_sasl.sasl_conn);
  session->smtp_sasl.sasl_conn = NULL;
  mailsasl_unref();
 free_secret:
  free(session->smtp_sasl.sasl_secret);
  session->smtp_sasl.sasl_secret = NULL;
 err:
  return res;
#else
  return MAILSMTP_ERROR_NOT_IMPLEMENTED;
#endif
}
Exemple #18
0
static int login(struct backend *s, const char *userid,
                 sasl_callback_t *cb, const char **status,
                 int noauth __attribute__((unused)))
{
    int r = 0;
    socklen_t addrsize;
    struct sockaddr_storage saddr_l, saddr_r;
    char remoteip[60], localip[60];
    static struct buf buf = BUF_INITIALIZER;
    sasl_security_properties_t secprops =
        { 0, 0xFF, PROT_BUFSIZE, 0, NULL, NULL }; /* default secprops */
    const char *mech_conf, *pass, *clientout = NULL;
    struct auth_scheme_t *scheme = NULL;
    unsigned need_tls = 0, tls_done = 0, auth_done = 0, clientoutlen;
    hdrcache_t hdrs = NULL;

    if (status) *status = NULL;

    /* set the IP addresses */
    addrsize = sizeof(struct sockaddr_storage);
    if (getpeername(s->sock, (struct sockaddr *) &saddr_r, &addrsize) ||
        iptostring((struct sockaddr *) &saddr_r, addrsize, remoteip, 60)) {
        if (status) *status = "Failed to get remote IP address";
        return SASL_FAIL;
    }

    addrsize = sizeof(struct sockaddr_storage);
    if (getsockname(s->sock, (struct sockaddr *) &saddr_l, &addrsize) ||
        iptostring((struct sockaddr *) &saddr_l, addrsize, localip, 60)) {
        if (status) *status = "Failed to get local IP address";
        return SASL_FAIL;
    }

    /* Create callbacks, if necessary */
    if (!cb) {
        buf_setmap(&buf, s->hostname, strcspn(s->hostname, "."));
        buf_appendcstr(&buf, "_password");
        pass = config_getoverflowstring(buf_cstring(&buf), NULL);
        if (!pass) pass = config_getstring(IMAPOPT_PROXY_PASSWORD);
        cb = mysasl_callbacks(NULL, /* userid */
                              config_getstring(IMAPOPT_PROXY_AUTHNAME),
                              config_getstring(IMAPOPT_PROXY_REALM),
                              pass);
        s->sasl_cb = cb;
    }

    /* Create SASL context */
    r = sasl_client_new(s->prot->sasl_service, s->hostname,
                        localip, remoteip, cb, SASL_USAGE_FLAGS, &s->saslconn);
    if (r != SASL_OK) goto done;

    r = sasl_setprop(s->saslconn, SASL_SEC_PROPS, &secprops);
    if (r != SASL_OK) goto done;

    /* Get SASL mechanism list.  We can force a particular
       mechanism using a <shorthost>_mechs option */
    buf_setmap(&buf, s->hostname, strcspn(s->hostname, "."));
    buf_appendcstr(&buf, "_mechs");
    if (!(mech_conf = config_getoverflowstring(buf_cstring(&buf), NULL))) {
        mech_conf = config_getstring(IMAPOPT_FORCE_SASL_CLIENT_MECH);
    }

    do {
        unsigned code;
        const char **hdr, *errstr, *serverin;
        char base64[BASE64_BUF_SIZE+1];
        unsigned int serverinlen;
        struct body_t resp_body;
#ifdef SASL_HTTP_REQUEST
        sasl_http_request_t httpreq = { "OPTIONS",      /* Method */
                                        "*",            /* URI */
                                        (u_char *) "",  /* Empty body */
                                        0,              /* Zero-length body */
                                        0 };            /* Persistent cxn? */
#endif

        /* Base64 encode any client response, if necessary */
        if (clientout && scheme && (scheme->flags & AUTH_BASE64)) {
            r = sasl_encode64(clientout, clientoutlen,
                              base64, BASE64_BUF_SIZE, &clientoutlen);
            if (r != SASL_OK) break;

            clientout = base64;
        }

        /* Send Authorization and/or Upgrade request to server */
        prot_puts(s->out, "OPTIONS * HTTP/1.1\r\n");
        prot_printf(s->out, "Host: %s\r\n", s->hostname);
        prot_printf(s->out, "User-Agent: %s\r\n", buf_cstring(&serverinfo));
        if (scheme) {
            prot_printf(s->out, "Authorization: %s %s\r\n",
                        scheme->name, clientout ? clientout : "");
            prot_printf(s->out, "Authorize-As: %s\r\n",
                        userid ? userid : "anonymous");
        }
        else {
            prot_printf(s->out, "Upgrade: %s\r\n", TLS_VERSION);
            if (need_tls) {
                prot_puts(s->out, "Connection: Upgrade\r\n");
                need_tls = 0;
            }
            prot_puts(s->out, "Authorization: \r\n");
        }
        prot_puts(s->out, "\r\n");
        prot_flush(s->out);

        serverin = clientout = NULL;
        serverinlen = clientoutlen = 0;

        /* Read response(s) from backend until final response or error */
        do {
            resp_body.flags = BODY_DISCARD;
            r = http_read_response(s, METH_OPTIONS, &code, NULL,
                                   &hdrs, &resp_body, &errstr);
            if (r) {
                if (status) *status = errstr;
                break;
            }

            if (code == 101) {  /* Switching Protocols */
                if (tls_done) {
                    r = HTTP_BAD_GATEWAY;
                    if (status) *status = "TLS already active";
                    break;
                }
                else if (backend_starttls(s, NULL, NULL, NULL)) {
                    r = HTTP_SERVER_ERROR;
                    if (status) *status = "Unable to start TLS";
                    break;
                }
                else tls_done = 1;
            }
        } while (code < 200);

        switch (code) {
        default: /* Failure */
            if (!r) {
                r = HTTP_BAD_GATEWAY;
                if (status) {
                    buf_reset(&buf);
                    buf_printf(&buf,
                               "Unexpected status code from backend: %u", code);
                    *status = buf_cstring(&buf);
                }
            }
            break;

        case 426: /* Upgrade Required */
            if (tls_done) {
                r = HTTP_BAD_GATEWAY;
                if (status) *status = "TLS already active";
            }
            else need_tls = 1;
            break;

        case 200: /* OK */
            if (scheme->recv_success &&
                (serverin = scheme->recv_success(hdrs))) {
                /* Process success data */
                serverinlen = strlen(serverin);
                goto challenge;
            }
            break;

        case 401: /* Unauthorized */
            if (auth_done) {
                r = SASL_BADAUTH;
                break;
            }

            if (!serverin) {
                int i = 0;

                hdr = spool_getheader(hdrs, "WWW-Authenticate");

                if (!scheme) {
                    unsigned avail_auth_schemes = 0;
                    const char *mech = NULL;
                    size_t len;

                    /* Compare authentication schemes offered in
                     * WWW-Authenticate header(s) to what we support */
                    buf_reset(&buf);
                    for (i = 0; hdr && hdr[i]; i++) {
                        len = strcspn(hdr[i], " ");

                        for (scheme = auth_schemes; scheme->name; scheme++) {
                            if (!strncmp(scheme->name, hdr[i], len) &&
                                !((scheme->flags & AUTH_NEED_PERSIST) &&
                                  (resp_body.flags & BODY_CLOSE))) {
                                /* Tag the scheme as available */
                                avail_auth_schemes |= (1 << scheme->idx);

                                /* Add SASL-based schemes to SASL mech list */
                                if (scheme->saslmech) {
                                    if (buf_len(&buf)) buf_putc(&buf, ' ');
                                    buf_appendcstr(&buf, scheme->saslmech);
                                }
                                break;
                            }
                        }
                    }

                    /* If we have a mech_conf, use it */
                    if (mech_conf && buf_len(&buf)) {
                        char *conf = xstrdup(mech_conf);
                        char *newmechlist =
                            intersect_mechlists(conf,
                                                (char *) buf_cstring(&buf));

                        if (newmechlist) {
                            buf_setcstr(&buf, newmechlist);
                            free(newmechlist);
                        }
                        else {
                            syslog(LOG_DEBUG, "%s did not offer %s",
                                   s->hostname, mech_conf);
                            buf_reset(&buf);
                        }
                        free(conf);
                    }

#ifdef SASL_HTTP_REQUEST
                    /* Set HTTP request as specified above (REQUIRED) */
                    httpreq.non_persist = (resp_body.flags & BODY_CLOSE);
                    sasl_setprop(s->saslconn, SASL_HTTP_REQUEST, &httpreq);
#endif

                    /* Try to start SASL exchange using available mechs */
                    r = sasl_client_start(s->saslconn, buf_cstring(&buf),
                                          NULL,         /* no prompts */
                                          NULL, NULL,   /* no initial resp */
                                          &mech);

                    if (mech) {
                        /* Find auth scheme associated with chosen SASL mech */
                        for (scheme = auth_schemes; scheme->name; scheme++) {
                            if (scheme->saslmech &&
                                !strcmp(scheme->saslmech, mech)) break;
                        }
                    }
                    else {
                        /* No matching SASL mechs - try Basic */
                        scheme = &auth_schemes[AUTH_BASIC];
                        if (!(avail_auth_schemes & (1 << scheme->idx))) {
                            need_tls = !tls_done;
                            break;  /* case 401 */
                        }
                    }

                    /* Find the associated WWW-Authenticate header */
                    for (i = 0; hdr && hdr[i]; i++) {
                        len = strcspn(hdr[i], " ");
                        if (!strncmp(scheme->name, hdr[i], len)) break;
                    }
                }

                /* Get server challenge, if any */
                if (hdr) {
                    const char *p = strchr(hdr[i], ' ');
                    serverin = p ? ++p : "";
                    serverinlen = strlen(serverin);
                }
            }

        challenge:
            if (serverin) {
                /* Perform the next step in the auth exchange */

                if (scheme->idx == AUTH_BASIC) {
                    /* Don't care about "realm" in server challenge */
                    const char *authid =
                        callback_getdata(s->saslconn, cb, SASL_CB_AUTHNAME);
                    pass = callback_getdata(s->saslconn, cb, SASL_CB_PASS);

                    buf_reset(&buf);
                    buf_printf(&buf, "%s:%s", authid, pass);
                    clientout = buf_cstring(&buf);
                    clientoutlen = buf_len(&buf);
                    auth_done = 1;
                }
                else {
                    /* Base64 decode any server challenge, if necessary */
                    if (serverin && (scheme->flags & AUTH_BASE64)) {
                        r = sasl_decode64(serverin, serverinlen,
                                          base64, BASE64_BUF_SIZE, &serverinlen);
                        if (r != SASL_OK) break;  /* case 401 */

                        serverin = base64;
                    }

                    /* SASL mech (Digest, Negotiate, NTLM) */
                    r = sasl_client_step(s->saslconn, serverin, serverinlen,
                                         NULL,          /* no prompts */
                                         &clientout, &clientoutlen);
                    if (r == SASL_OK) auth_done = 1;
                }
            }
            break;  /* case 401 */
        }

    } while (need_tls || clientout);

  done:
    if (hdrs) spool_free_hdrcache(hdrs);

    if (r && status && !*status) *status = sasl_errstring(r, NULL, NULL);

    return r;
}
Exemple #19
0
HIDDEN int ws_start_channel(struct transaction_t *txn, const char *protocol,
                            int (*data_cb)(struct buf *inbuf, struct buf *outbuf,
                                           struct buf *logbuf, void **rock))
{
    int r;
    const char **hdr, *accept = NULL;
    wslay_event_context_ptr ev;
    struct ws_context *ctx;
    struct wslay_event_callbacks callbacks = {
        recv_cb,
        send_cb,
        NULL,
        NULL,
        NULL,
        NULL,
        on_msg_recv_cb
    };

    /* Check for supported WebSocket version */
    hdr = spool_getheader(txn->req_hdrs, "Sec-WebSocket-Version");
    if (!hdr) {
        txn->error.desc = "Missing WebSocket version";
        return HTTP_BAD_REQUEST;
    }
    else if (hdr[1]) {
        txn->error.desc = "Multiple WebSocket versions";
        return HTTP_BAD_REQUEST;
    }
    else if (strcmp(hdr[0], WS_VERSION)) {
        txn->error.desc = "Unsupported WebSocket version";
        return HTTP_UPGRADE;
    }

    if (protocol) {
        /* Check for supported WebSocket subprotocol */
        int i, found = 0;

        hdr = spool_getheader(txn->req_hdrs, "Sec-WebSocket-Protocol");
        if (!hdr) {
            txn->error.desc = "Missing WebSocket protocol";
            return HTTP_BAD_REQUEST;
        }

        for (i = 0; !found && hdr[i]; i++) {
            tok_t tok = TOK_INITIALIZER(hdr[i], ",", TOK_TRIMLEFT|TOK_TRIMRIGHT);
            char *token;

            while ((token = tok_next(&tok))) {
                if (!strcmp(token, protocol)) {
                    found = 1;
                    break;
                }
            }
            tok_fini(&tok);
        }
        if (!found) {
            txn->error.desc = "Unsupported WebSocket protocol";
            return HTTP_BAD_REQUEST;
        }
    }

    if (txn->flags.ver == VER_1_1) {
        unsigned char sha1buf[SHA1_DIGEST_LENGTH];

        /* Check for WebSocket client key */
        hdr = spool_getheader(txn->req_hdrs, "Sec-WebSocket-Key");
        if (!hdr) {
            txn->error.desc = "Missing WebSocket client key";
            return HTTP_BAD_REQUEST;
        }
        else if (hdr[1]) {
            txn->error.desc = "Multiple WebSocket client keys";
            return HTTP_BAD_REQUEST;
        }
        else if (strlen(hdr[0]) != WS_CKEY_LEN) {
            txn->error.desc = "Invalid WebSocket client key";
            return HTTP_BAD_REQUEST;
        }

        /* Create WebSocket accept key */
        buf_setcstr(&txn->buf, hdr[0]);
        buf_appendcstr(&txn->buf, WS_GUID);
        xsha1((u_char *) buf_base(&txn->buf), buf_len(&txn->buf), sha1buf);

        buf_ensure(&txn->buf, WS_AKEY_LEN+1);
        accept = buf_base(&txn->buf);

        r = sasl_encode64((char *) sha1buf, SHA1_DIGEST_LENGTH,
                          (char *) accept, WS_AKEY_LEN+1, NULL);
        if (r != SASL_OK) syslog(LOG_WARNING, "sasl_encode64: %d", r);
    }

    /* Create server context */
    r = wslay_event_context_server_init(&ev, &callbacks, txn);
    if (r) {
        syslog(LOG_WARNING,
               "wslay_event_context_init: %s", wslay_strerror(r));
        return HTTP_SERVER_ERROR;
    }

    /* Create channel context */
    ctx = xzmalloc(sizeof(struct ws_context));
    ctx->event = ev;
    ctx->accept = accept;
    ctx->protocol = protocol;
    ctx->data_cb = data_cb;
    txn->ws_ctx = ctx;

    /* Check for supported WebSocket extensions */
    parse_extensions(txn);

    /* Prepare log buffer */

    /* Add client data */
    buf_printf(&ctx->log, "%s", txn->conn->clienthost);
    if (httpd_userid) buf_printf(&ctx->log, " as \"%s\"", httpd_userid);
    if ((hdr = spool_getheader(txn->req_hdrs, "User-Agent"))) {
        buf_printf(&ctx->log, " with \"%s\"", hdr[0]);
        if ((hdr = spool_getheader(txn->req_hdrs, "X-Client")))
            buf_printf(&ctx->log, " by \"%s\"", hdr[0]);
        else if ((hdr = spool_getheader(txn->req_hdrs, "X-Requested-With")))
            buf_printf(&ctx->log, " by \"%s\"", hdr[0]);
    }

    /* Add request-line */
    buf_printf(&ctx->log, "; \"WebSocket/%s via %s\"",
               protocol ? protocol : "echo" , txn->req_line.ver);
    ctx->log_tail = buf_len(&ctx->log);

    /* Tell client that WebSocket negotiation has succeeded */
    if (txn->conn->sess_ctx) {
        /* Treat WS data as chunked response */
        txn->flags.te = TE_CHUNKED;

        response_header(HTTP_OK, txn);

        /* Force the response to the client immediately */
        prot_flush(httpd_out);
    }
    else response_header(HTTP_SWITCH_PROT, txn);

    /* Set connection as non-blocking */
    prot_NONBLOCK(txn->conn->pin);

    /* Don't do telemetry logging in prot layer */
    prot_setlog(txn->conn->pin, PROT_NO_FD);
    prot_setlog(txn->conn->pout, PROT_NO_FD);

    return 0;
}
Exemple #20
0
int
ArgusSendSaslString(FILE *f, const char *s, int l, int mode)
{
   char *buf = NULL, *ptr = NULL, error[128];
   unsigned int al, len;
   int result, size, tsize;

   switch (mode) {
      case SASL_OK: {
         if ((s == NULL) || (l == 0)) {
            ptr = "D: ";
            tsize = 3;
            break;
         }
      }
      case SASL_CONTINUE: {
         ptr = "S: ";
         tsize = 3;
         break;
      }
      default: {
         sprintf (error, "E: [%d]", mode);
         ptr = error;
         tsize = strlen(error);
         break;
      }
   }

   if (ferror(f))
      clearerr(f);

   while ((size = fwrite(ptr, 1, tsize, f)) != tsize) {
      if (size >= 0) {
         tsize -= size;
         ptr += size;
      } else {
         if (ferror(f))
            ArgusLog (LOG_ERR, "ArgusSendSaslString: error %d", ferror(f));
      }
   }

   if (l > 0) {
      al = (((l / 3) + 1) * 4) + 1;

      if ((buf = malloc(al)) == NULL)
         ArgusLog (LOG_ERR, "malloc: error %s", strerror(errno));

      if ((ptr = buf) != NULL) {
         result = sasl_encode64(s, l, buf, al, &len);

         if (result == SASL_OK) {
            tsize = len;
            while ((size = fwrite(ptr, 1, tsize, f)) != tsize) {
               if (size >= 0) {
                  tsize -= size;
                  ptr += size;
               } else {
                  if (ferror(f))
                     ArgusLog (LOG_ERR, "ArgusSendSaslString: error %d", ferror(f));
               }
            }
         }
      }

      free(buf);
   }

   ptr = "\n";
   tsize = 1;
   while ((size = fwrite(ptr, 1, tsize, f)) != tsize) {
      if (size >= 0) {
         tsize -= size;
         ptr += size;
      } else {
         if (ferror(f))
            ArgusLog (LOG_ERR, "ArgusSendSaslString: error %d", ferror(f));
      }
   }

   fflush(f);

#ifdef ARGUSDEBUG
   ArgusDebug (2, "ArgusSendSaslString(0x%x, 0x%x, %d) %s", f, s, l, s);
#endif
   return len;
}
Exemple #21
0
/*
 * mgmt_config_save2scf() saves main configuration to scf
 * See also : mgmt_get_main_config()
 */
Boolean_t
mgmt_config_save2scf()
{
	targ_scf_t *h = NULL;
	scf_property_t *prop = NULL;
	scf_value_t *value = NULL;
	scf_iter_t *iter = NULL;
	char pgname[64];
	char passcode[32];
	unsigned int	outlen;
	tgt_node_t	*n = NULL;
	tgt_node_t	*pn = NULL;
	tgt_node_t	*tn = NULL;
	scf_transaction_t *tx = NULL;
	secret_list_t	*sl_head;
	secret_list_t	*sl_tail;

	h = mgmt_handle_init();

	if (h == NULL)
		return (False);

	prop = scf_property_create(h->t_handle);
	value = scf_value_create(h->t_handle);
	iter = scf_iter_create(h->t_handle);

	(void) pthread_mutex_lock(&scf_conf_mutex);

	if (mgmt_transaction_start(h, "iscsitgt", "basic") == True) {
		scf_pg_delete(h->t_pg);
		mgmt_transaction_end(h);
	}

	if (mgmt_transaction_start(h, "passwords", "application") == True) {
		scf_pg_delete(h->t_pg);
		mgmt_transaction_end(h);
	}

	if (scf_iter_service_pgs_typed(iter, h->t_service, "configuration")
	    == -1) {
		goto error;
	}

	tx = scf_transaction_create(h->t_handle);
	while (scf_iter_next_pg(iter, h->t_pg) > 0) {
		scf_transaction_start(tx, h->t_pg);
		scf_pg_delete(h->t_pg);
		scf_transaction_commit(tx);
	}
	scf_transaction_reset(tx);
	scf_transaction_destroy(tx);

	sl_head = (secret_list_t *)calloc(1, sizeof (secret_list_t));
	sl_tail = sl_head;

	if (mgmt_transaction_start(h, "iscsitgt", "basic") == True) {
		for (n = main_config->x_child; n; n = n->x_sibling) {
			if (strcmp(n->x_name,
			    XML_ELEMENT_CHAPSECRET) == 0) {
				sl_tail->next =  (secret_list_t *)
				    calloc(1, sizeof (secret_list_t));
				sl_tail = sl_tail->next;
				sl_tail->name = strdup("main");
				sl_tail->secret = strdup(n->x_value);
				continue;
			}
			/* so does the radius server secret */
			if (strcmp(n->x_name,
			    XML_ELEMENT_RAD_SECRET) == 0) {
				sl_tail->next =  (secret_list_t *)
				    calloc(1, sizeof (secret_list_t));
				sl_tail = sl_tail->next;
				sl_tail->name = strdup("radius");
				sl_tail->secret = strdup(n->x_value);
				continue;
			}
			if (n->x_child == NULL) {
				new_property(h, n);
			}
		}
		new_property(h, main_config->x_attr);
		n = tgt_node_alloc(ISCSI_MODIFY_AUTHNAME, String,
		    ISCSI_AUTH_MODIFY);
		new_property(h, n);
		tgt_node_free(n);
		n = tgt_node_alloc(ISCSI_VALUE_AUTHNAME, String,
		    ISCSI_AUTH_VALUE);
		new_property(h, n);
		tgt_node_free(n);
		mgmt_transaction_end(h);
	}

	/* now update target/initiator/tpgt information */
	for (n = main_config->x_child; n; n = n->x_sibling) {
		if (n->x_child == NULL)
			continue;

		snprintf(pgname, sizeof (pgname), "%s_%s", n->x_name,
		    n->x_value);

		if (mgmt_transaction_start(h, pgname, "configuration")
		    == True) {
			for (pn = n->x_child; pn; pn = pn->x_sibling) {
				if (strcmp(pn->x_name,
				    XML_ELEMENT_CHAPSECRET) == 0) {
					sl_tail->next =  (secret_list_t *)
					    calloc(1, sizeof (secret_list_t));
					sl_tail = sl_tail->next;
					sl_tail->name = (char *)
					    calloc(1, strlen(n->x_value) + 3);
					snprintf(sl_tail->name,
					    strlen(n->x_value) + 3,
					    "I_%s", n->x_value);
					sl_tail->secret = strdup(pn->x_value);
					continue;
				}
				if (pn->x_child == NULL) {
					/* normal property */
					new_property(h, pn);
				} else {
					/* pn -> xxx-list */
					new_value_list(h, pn);
				}
				tn = tgt_node_alloc(ISCSI_MODIFY_AUTHNAME,
				    String, ISCSI_AUTH_MODIFY);
				new_property(h, tn);
				tgt_node_free(tn);
				tn = tgt_node_alloc(ISCSI_VALUE_AUTHNAME,
				    String, ISCSI_AUTH_VALUE);
				new_property(h, tn);
				tgt_node_free(tn);
			}
			mgmt_transaction_end(h);
		}
	}

	if (mgmt_transaction_start(h, "passwords", "application") == True) {
		while (sl_head != NULL) {
			/* Here we use sl_tail as a temporari var */
			sl_tail = sl_head->next;
			if (sl_head->name) {
				/* max length of encoded passwd is 24B */
				sasl_encode64(sl_head->secret,
				    strlen(sl_head->secret), passcode,
				    sizeof (passcode), &outlen);

				n = tgt_node_alloc(sl_head->name, String,
				    passcode);
				new_property(h, n);
				tgt_node_free(n);
			}
			if (sl_head->name)
				free(sl_head->name);
			if (sl_head->secret)
				free(sl_head->secret);
			free(sl_head);
			sl_head = sl_tail;
		}
		n = tgt_node_alloc(ISCSI_READ_AUTHNAME, String,
		    ISCSI_AUTH_READ);
		new_property(h, n);
		tgt_node_free(n);
		n = tgt_node_alloc(ISCSI_VALUE_AUTHNAME, String,
		    ISCSI_AUTH_VALUE);
		new_property(h, n);
		tgt_node_free(n);
		n = tgt_node_alloc(ISCSI_MODIFY_AUTHNAME, String,
		    ISCSI_AUTH_MODIFY);
		new_property(h, n);
		tgt_node_free(n);
		mgmt_transaction_end(h);
	}

	if (smf_refresh_instance(SA_TARGET_SVC_INSTANCE_FMRI) != 0)
		goto error;

	(void) pthread_mutex_unlock(&scf_conf_mutex);
	scf_iter_destroy(iter);
	scf_value_destroy(value);
	scf_property_destroy(prop);
	return (True);

error:
	(void) pthread_mutex_unlock(&scf_conf_mutex);
	scf_iter_destroy(iter);
	scf_value_destroy(value);
	scf_property_destroy(prop);
	mgmt_handle_fini(h);
	return (False);
}
Exemple #22
0
/* imap_auth_sasl: Default authenticator if available. */
imap_auth_res_t imap_auth_sasl (IMAP_DATA* idata, const char* method)
{
  sasl_conn_t* saslconn;
  sasl_interact_t* interaction = NULL;
  int rc, irc;
  char buf[HUGE_STRING];
  const char* mech;
  const char *pc = NULL;
  unsigned int len, olen;
  unsigned char client_start;

  if (mutt_sasl_client_new (idata->conn, &saslconn) < 0)
  {
    dprint (1, (debugfile,
      "imap_auth_sasl: Error allocating SASL connection.\n"));
    return IMAP_AUTH_FAILURE;
  }

  rc = SASL_FAIL;

  /* If the user hasn't specified a method, use any available */
  if (!method)
  {
    method = idata->capstr;

    /* hack for SASL ANONYMOUS support:
     * 1. Fetch username. If it's "" or "anonymous" then
     * 2. attempt sasl_client_start with only "AUTH=ANONYMOUS" capability
     * 3. if sasl_client_start fails, fall through... */

    if (mutt_account_getuser (&idata->conn->account))
      return IMAP_AUTH_FAILURE;

    if (mutt_bit_isset (idata->capabilities, AUTH_ANON) &&
	(!idata->conn->account.user[0] ||
	 !ascii_strncmp (idata->conn->account.user, "anonymous", 9)))
      rc = sasl_client_start (saslconn, "AUTH=ANONYMOUS", NULL, &pc, &olen, 
                              &mech);
  } else if (!ascii_strcasecmp ("login", method) &&
	!strstr (NONULL (idata->capstr), "AUTH=LOGIN"))
    /* do not use SASL login for regular IMAP login (#3556) */
    return IMAP_AUTH_UNAVAIL;
  
  if (rc != SASL_OK && rc != SASL_CONTINUE)
    do
    {
      rc = sasl_client_start (saslconn, method, &interaction,
        &pc, &olen, &mech);
      if (rc == SASL_INTERACT)
	mutt_sasl_interact (interaction);
    }
    while (rc == SASL_INTERACT);

  client_start = (olen > 0);

  if (rc != SASL_OK && rc != SASL_CONTINUE)
  {
    if (method)
      dprint (2, (debugfile, "imap_auth_sasl: %s unavailable\n", method));
    else
      dprint (1, (debugfile, "imap_auth_sasl: Failure starting authentication exchange. No shared mechanisms?\n"));
    /* SASL doesn't support LOGIN, so fall back */

    return IMAP_AUTH_UNAVAIL;
  }

  mutt_message (_("Authenticating (%s)..."), mech);

  snprintf (buf, sizeof (buf), "AUTHENTICATE %s", mech);
  if (mutt_bit_isset (idata->capabilities, SASL_IR) && client_start)
  {
    len = mutt_strlen (buf);
    buf[len++] = ' ';
    if (sasl_encode64 (pc, olen, buf + len, sizeof (buf) - len, &olen) != SASL_OK)
    {
      dprint (1, (debugfile, "imap_auth_sasl: error base64-encoding client response.\n"));
      goto bail;
    }
    client_start = olen = 0;
  }
  imap_cmd_start (idata, buf);
  irc = IMAP_CMD_CONTINUE;

  /* looping protocol */
  while (rc == SASL_CONTINUE || olen > 0)
  {
    do
      irc = imap_cmd_step (idata);
    while (irc == IMAP_CMD_CONTINUE);

    if (irc == IMAP_CMD_BAD || irc == IMAP_CMD_NO)
      goto bail;

    if (irc == IMAP_CMD_RESPOND)
    {
      /* Exchange incorrectly returns +\r\n instead of + \r\n */
      if (idata->buf[1] == '\0')
      {
	buf[0] = '\0';
	len = 0;
      }
      else if (sasl_decode64 (idata->buf+2, strlen (idata->buf+2), buf,
			      LONG_STRING-1, &len) != SASL_OK)
      {
	dprint (1, (debugfile, "imap_auth_sasl: error base64-decoding server response.\n"));
	goto bail;
      }
    }

    /* client-start is only available with the SASL-IR extension, but
     * SASL 2.1 seems to want to use it regardless, at least for DIGEST
     * fast reauth. Override if the server sent an initial continuation */
    if (!client_start || buf[0])
    {
      do
      {
	rc = sasl_client_step (saslconn, buf, len, &interaction, &pc, &olen);
	if (rc == SASL_INTERACT)
	  mutt_sasl_interact (interaction);
      }
      while (rc == SASL_INTERACT);
    }
    else
      client_start = 0;

    /* send out response, or line break if none needed */
    if (olen)
    {
      if (sasl_encode64 (pc, olen, buf, sizeof (buf), &olen) != SASL_OK)
      {
	dprint (1, (debugfile, "imap_auth_sasl: error base64-encoding client response.\n"));
	goto bail;
      }
    }
    
    if (irc == IMAP_CMD_RESPOND)
    {
      strfcpy (buf + olen, "\r\n", sizeof (buf) - olen);
      mutt_socket_write (idata->conn, buf);
    }

    /* If SASL has errored out, send an abort string to the server */
    if (rc < 0)
    {
      mutt_socket_write (idata->conn, "*\r\n");
      dprint (1, (debugfile, "imap_auth_sasl: sasl_client_step error %d\n",rc));
    }
	  
    olen = 0;
  }

  while (irc != IMAP_CMD_OK)
    if ((irc = imap_cmd_step (idata)) != IMAP_CMD_CONTINUE)
      break;

  if (rc != SASL_OK)
    goto bail;

  if (imap_code (idata->buf))
  {
    mutt_sasl_setup_conn (idata->conn, saslconn);
    return IMAP_AUTH_SUCCESS;
  }

 bail:
  sasl_dispose (&saslconn);

  if (method)
  {
    dprint (2, (debugfile, "imap_auth_sasl: %s failed\n", method));
    return IMAP_AUTH_UNAVAIL;
  }

  mutt_error _("SASL authentication failed.");
  mutt_sleep(2);

  return IMAP_AUTH_FAILURE;
}
Exemple #23
0
static bool
_mongoc_cyrus_start (mongoc_cyrus_t *sasl,
                     uint8_t *outbuf,
                     uint32_t outbufmax,
                     uint32_t *outbuflen,
                     bson_error_t *error)
{
   const char *service_name = "mongodb";
   const char *service_host = "";
   const char *mechanism = NULL;
   const char *raw = NULL;
   unsigned raw_len = 0;
   int status;

   BSON_ASSERT (sasl);
   BSON_ASSERT (outbuf);
   BSON_ASSERT (outbufmax);
   BSON_ASSERT (outbuflen);

   if (sasl->credentials.service_name) {
      service_name = sasl->credentials.service_name;
   }

   if (sasl->credentials.service_host) {
      service_host = sasl->credentials.service_host;
   }

   status = sasl_client_new (
      service_name, service_host, NULL, NULL, sasl->callbacks, 0, &sasl->conn);
   TRACE ("Created new sasl client %s",
          status == SASL_OK ? "successfully" : "UNSUCCESSFULLY");
   if (_mongoc_cyrus_is_failure (status, error)) {
      return false;
   }

   status = sasl_client_start (sasl->conn,
                               sasl->credentials.mechanism,
                               &sasl->interact,
                               &raw,
                               &raw_len,
                               &mechanism);
   TRACE ("Started the sasl client %s",
          status == SASL_CONTINUE ? "successfully" : "UNSUCCESSFULLY");
   if (_mongoc_cyrus_is_failure (status, error)) {
      return false;
   }

   if ((0 != strcasecmp (mechanism, "GSSAPI")) &&
       (0 != strcasecmp (mechanism, "PLAIN"))) {
      bson_set_error (error,
                      MONGOC_ERROR_SASL,
                      SASL_NOMECH,
                      "SASL Failure: invalid mechanism \"%s\"",
                      mechanism);
      return false;
   }


   status = sasl_encode64 (raw, raw_len, (char *) outbuf, outbufmax, outbuflen);
   if (_mongoc_cyrus_is_failure (status, error)) {
      return false;
   }

   return true;
}
Exemple #24
0
int mailpop3_auth(mailpop3 * f, const char * auth_type,
    const char * server_fqdn,
    const char * local_ip_port,
    const char * remote_ip_port,
    const char * login, const char * auth_name,
    const char * password, const char * realm)
{
#ifdef USE_SASL
  int r;
  char command[POP3_STRING_SIZE];
  sasl_callback_t sasl_callback[5];
  const char * sasl_out;
  unsigned sasl_out_len;
  const char * mechusing;
  sasl_secret_t * secret;
  int res;
  size_t len;
  char * encoded;
  unsigned int encoded_len;
  unsigned int max_encoded;
  
  sasl_callback[0].id = SASL_CB_GETREALM;
  sasl_callback[0].proc =  sasl_getrealm;
  sasl_callback[0].context = f;
  sasl_callback[1].id = SASL_CB_USER;
  sasl_callback[1].proc =  sasl_getsimple;
  sasl_callback[1].context = f;
  sasl_callback[2].id = SASL_CB_AUTHNAME;
  sasl_callback[2].proc =  sasl_getsimple;
  sasl_callback[2].context = f; 
  sasl_callback[3].id = SASL_CB_PASS;
  sasl_callback[3].proc =  sasl_getsecret;
  sasl_callback[3].context = f;
  sasl_callback[4].id = SASL_CB_LIST_END;
  sasl_callback[4].proc =  NULL;
  sasl_callback[4].context = NULL;
  
  len = strlen(password);
  secret = malloc(sizeof(* secret) + len);
  if (secret == NULL) {
    res = MAILPOP3_ERROR_MEMORY;
    goto err;
  }
  secret->len = len;
  memcpy(secret->data, password, len + 1);
  
  f->pop3_sasl.sasl_server_fqdn = server_fqdn;
  f->pop3_sasl.sasl_login = login;
  f->pop3_sasl.sasl_auth_name = auth_name;
  f->pop3_sasl.sasl_password = password;
  f->pop3_sasl.sasl_realm = realm;
  f->pop3_sasl.sasl_secret = secret;
  
  /* init SASL */
  if (f->pop3_sasl.sasl_conn != NULL) {
    sasl_dispose((sasl_conn_t **) &f->pop3_sasl.sasl_conn);
    f->pop3_sasl.sasl_conn = NULL;
  }
  else {
    mailsasl_ref();
  }
  
  r = sasl_client_new("pop", server_fqdn,
      local_ip_port, remote_ip_port, sasl_callback, 0,
      (sasl_conn_t **) &f->pop3_sasl.sasl_conn);
  if (r != SASL_OK) {
    res = MAILPOP3_ERROR_BAD_USER;
    goto free_secret;
  }
  
  r = sasl_client_start(f->pop3_sasl.sasl_conn,
      auth_type, NULL, &sasl_out, &sasl_out_len, &mechusing);
  if ((r != SASL_CONTINUE) && (r != SASL_OK)) {
    res = MAILPOP3_ERROR_BAD_USER;
    goto free_sasl_conn;
  }
  
  snprintf(command, POP3_STRING_SIZE, "AUTH %s\r\n", auth_type);
  
  r = send_command(f, command);
  if (r == -1) {
    res = MAILPOP3_ERROR_STREAM;
    goto free_sasl_conn;
  }
  
  while (1) {
    char * response;
    
    response = read_line(f);
    
    r = parse_auth(f, response);
    switch (r) {
    case RESPONSE_OK:
      f->pop3_state = POP3_STATE_TRANSACTION;
      res = MAILPOP3_NO_ERROR;
      goto free_sasl_conn;
      
    case RESPONSE_ERR:
      res = MAILPOP3_ERROR_BAD_USER;
      goto free_sasl_conn;
    
    case RESPONSE_AUTH_CONT:
      {
        size_t response_len;
        char * decoded;
        unsigned int decoded_len;
        unsigned int max_decoded;
        int got_response;
        
        got_response = 1;
        if (* f->pop3_response == '\0')
          got_response = 0;
        
        if (got_response) {
          char * p;
          
          p = strchr(f->pop3_response, '\r');
          if (p != NULL) {
            * p = '\0';
          }
          p = strchr(f->pop3_response, '\n');
          if (p != NULL) {
            * p = '\0';
          }
          response_len = strlen(f->pop3_response);
          max_decoded = response_len * 3 / 4;
          decoded = malloc(max_decoded + 1);
          if (decoded == NULL) {
            res = MAILPOP3_ERROR_MEMORY;
            goto free_sasl_conn;
          }
          
          r = sasl_decode64(f->pop3_response, response_len,
              decoded, max_decoded + 1, &decoded_len);
          
          if (r != SASL_OK) {
            free(decoded);
            res = MAILPOP3_ERROR_MEMORY;
            goto free_sasl_conn;
          }
          
          r = sasl_client_step(f->pop3_sasl.sasl_conn,
              decoded, decoded_len, NULL, &sasl_out, &sasl_out_len);
          
          free(decoded);
          
          if ((r != SASL_CONTINUE) && (r != SASL_OK)) {
            res = MAILPOP3_ERROR_BAD_USER;
            goto free_sasl_conn;
          }
        }
        
        max_encoded = ((sasl_out_len + 2) / 3) * 4;
        encoded = malloc(max_encoded + 1);
        if (encoded == NULL) {
          res = MAILPOP3_ERROR_MEMORY;
          goto free_sasl_conn;
        }
        
        r = sasl_encode64(sasl_out, sasl_out_len,
            encoded, max_encoded + 1, &encoded_len);
        if (r != SASL_OK) {
          free(encoded);
          res = MAILPOP3_ERROR_MEMORY;
          goto free_sasl_conn;
        }
        
        snprintf(command, POP3_STRING_SIZE, "%s\r\n", encoded);
        r = send_command(f, command);
        
        free(encoded);
        
        if (r == -1) {
          res = MAILPOP3_ERROR_STREAM;
          goto free_sasl_conn;
        }
      }
      break;
    }
  }

  f->pop3_state = POP3_STATE_TRANSACTION;
  res = MAILPOP3_NO_ERROR;
  
 free_sasl_conn:
  sasl_dispose((sasl_conn_t **) &f->pop3_sasl.sasl_conn);
  f->pop3_sasl.sasl_conn = NULL;
  mailsasl_unref();
 free_secret:
  free(f->pop3_sasl.sasl_secret);
  f->pop3_sasl.sasl_secret = NULL;
 err:
  return res;
#else
  return MAILPOP3_ERROR_BAD_USER;
#endif
}
Exemple #25
0
static int smtp_auth_sasl (CONNECTION* conn, const char* mechlist)
{
        sasl_conn_t* saslconn;
        sasl_interact_t* interaction = NULL;
        const char* mech;
        const char* data = NULL;
        unsigned int len;
        char buf[HUGE_STRING];
        int rc, saslrc;

        if (mutt_sasl_client_new (conn, &saslconn) < 0)
                return SMTP_AUTH_FAIL;

        do {
                rc = sasl_client_start (saslconn, mechlist, &interaction, &data, &len, &mech);
                if (rc == SASL_INTERACT)
                        mutt_sasl_interact (interaction);
        }
        while (rc == SASL_INTERACT);

        if (rc != SASL_OK && rc != SASL_CONTINUE) {
                dprint (2, (debugfile, "smtp_auth_sasl: %s unavailable\n", mech));
                sasl_dispose (&saslconn);
                return SMTP_AUTH_UNAVAIL;
        }

        if (!option(OPTNOCURSES))
                mutt_message (_("Authenticating (%s)..."), mech);

        snprintf (buf, sizeof (buf), "AUTH %s", mech);
        if (len) {
                safe_strcat (buf, sizeof (buf), " ");
                if (sasl_encode64 (data, len, buf + mutt_strlen (buf),
                sizeof (buf) - mutt_strlen (buf), &len) != SASL_OK) {
                        dprint (1, (debugfile, "smtp_auth_sasl: error base64-encoding client response.\n"));
                        goto fail;
                }
        }
        safe_strcat (buf, sizeof (buf), "\r\n");

        do {
                if (mutt_socket_write (conn, buf) < 0)
                        goto fail;
                if ((rc = mutt_socket_readln (buf, sizeof (buf), conn)) < 0)
                        goto fail;
                if (smtp_code (buf, rc, &rc) < 0)
                        goto fail;

                if (rc != smtp_ready)
                        break;

                if (sasl_decode64 (buf+4, strlen (buf+4), buf, sizeof (buf), &len) != SASL_OK) {
                        dprint (1, (debugfile, "smtp_auth_sasl: error base64-decoding server response.\n"));
                        goto fail;
                }

                do {
                        saslrc = sasl_client_step (saslconn, buf, len, &interaction, &data, &len);
                        if (saslrc == SASL_INTERACT)
                                mutt_sasl_interact (interaction);
                }
                while (saslrc == SASL_INTERACT);

                if (len) {
                        if (sasl_encode64 (data, len, buf, sizeof (buf), &len) != SASL_OK) {
                                dprint (1, (debugfile, "smtp_auth_sasl: error base64-encoding client response.\n"));
                                goto fail;
                        }
                }
                strfcpy (buf + len, "\r\n", sizeof (buf) - len);
        } while (rc == smtp_ready && saslrc != SASL_FAIL);

        if (smtp_success (rc)) {
                mutt_sasl_setup_conn (conn, saslconn);
                return SMTP_AUTH_SUCCESS;
        }

        fail:
        sasl_dispose (&saslconn);
        return SMTP_AUTH_FAIL;
}