コード例 #1
0
static const char *xsasl_cyrus_server_get_mechanism_list(XSASL_SERVER *xp)
{
    const char *myname = "xsasl_cyrus_server_get_mechanism_list";
    XSASL_CYRUS_SERVER *server = (XSASL_CYRUS_SERVER *) xp;
    MECHANISM_TYPE mechanism_list;
    MECHANISM_COUNT_TYPE mechanism_count;
    int     sasl_status;

    /*
     * Get the list of authentication mechanisms.
     */
#define UNSUPPORTED_USER	((char *) 0)
#define IGNORE_MECHANISM_LEN	((unsigned *) 0)

    if ((sasl_status = sasl_listmech(server->sasl_conn, UNSUPPORTED_USER,
				     "", " ", "",
				     &mechanism_list,
				     IGNORE_MECHANISM_LEN,
				     &mechanism_count)) != SASL_OK) {
	msg_warn("%s: %s", myname, xsasl_cyrus_strerror(sasl_status));
	return (0);
    }
    if (mechanism_count <= 0) {
	msg_warn("%s: no applicable SASL mechanisms", myname);
	return (0);
    }
    server->mechanism_list = mystrdup(mechanism_list);
#if SASL_VERSION_MAJOR < 2
    /* SASL version 1 doesn't free memory that it allocates. */
    free(mechanism_list);
#endif
    return (server->mechanism_list);
}
コード例 #2
0
int     xsasl_cyrus_server_first(XSASL_SERVER *xp, const char *sasl_method,
			          const char *init_response, VSTRING *reply)
{
    const char *myname = "xsasl_cyrus_server_first";
    XSASL_CYRUS_SERVER *server = (XSASL_CYRUS_SERVER *) xp;
    char   *dec_buffer;
    unsigned dec_length;
    unsigned reply_len;
    unsigned serveroutlen;
    int     sasl_status;
    SERVEROUT_TYPE serverout = 0;
    int     xsasl_status;

#if SASL_VERSION_MAJOR < 2
    const char *errstr = 0;

#endif

#define IFELSE(e1,e2,e3) ((e1) ? (e2) : (e3))

    if (msg_verbose)
	msg_info("%s: sasl_method %s%s%s", myname, sasl_method,
		 IFELSE(init_response, ", init_response ", ""),
		 IFELSE(init_response, init_response, ""));

    /*
     * SASL authentication protocol start-up. Process any initial client
     * response that was sent along in the AUTH command.
     */
    if (init_response) {
	reply_len = strlen(init_response);
	VSTRING_RESET(server->decoded);		/* Fix 200512 */
	VSTRING_SPACE(server->decoded, reply_len);
	if ((sasl_status = SASL_DECODE64(init_response, reply_len,
					 dec_buffer = STR(server->decoded),
					 vstring_avail(server->decoded),
					 &dec_length)) != SASL_OK) {
	    vstring_strcpy(reply, xsasl_cyrus_strerror(sasl_status));
	    return (XSASL_AUTH_FORM);
	}
	if (msg_verbose)
	    msg_info("%s: decoded initial response %s", myname, dec_buffer);
    } else {
	dec_buffer = 0;
	dec_length = 0;
    }
    sasl_status = SASL_SERVER_START(server->sasl_conn, sasl_method, dec_buffer,
				    dec_length, &serverout,
				    &serveroutlen, &errstr);
    xsasl_status = xsasl_cyrus_server_auth_response(sasl_status, serverout,
						    serveroutlen, reply);
#if SASL_VERSION_MAJOR < 2
    /* SASL version 1 doesn't free memory that it allocates. */
    free(serverout);
#endif
    return (xsasl_status);
}
コード例 #3
0
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);
    }
}
コード例 #4
0
static int xsasl_cyrus_server_next(XSASL_SERVER *xp, const char *request,
				           VSTRING *reply)
{
    const char *myname = "xsasl_cyrus_server_next";
    XSASL_CYRUS_SERVER *server = (XSASL_CYRUS_SERVER *) xp;
    unsigned dec_length;
    unsigned request_len;
    unsigned serveroutlen;
    int     sasl_status;
    SERVEROUT_TYPE serverout = 0;
    int     xsasl_status;

#if SASL_VERSION_MAJOR < 2
    const char *errstr = 0;

#endif

    request_len = strlen(request);
    VSTRING_RESET(server->decoded);		/* Fix 200512 */
    VSTRING_SPACE(server->decoded, request_len);
    if ((sasl_status = SASL_DECODE64(request, request_len,
				     STR(server->decoded),
				     vstring_avail(server->decoded),
				     &dec_length)) != SASL_OK) {
	vstring_strcpy(reply, xsasl_cyrus_strerror(sasl_status));
	return (XSASL_AUTH_FORM);
    }
    if (msg_verbose)
	msg_info("%s: decoded response: %.*s",
		 myname, (int) dec_length, STR(server->decoded));
    sasl_status = SASL_SERVER_STEP(server->sasl_conn, STR(server->decoded),
				   dec_length, &serverout,
				   &serveroutlen, &errstr);
    xsasl_status = xsasl_cyrus_server_auth_response(sasl_status, serverout,
						    serveroutlen, reply);
#if SASL_VERSION_MAJOR < 2
    /* SASL version 1 doesn't free memory that it allocates. */
    free(serverout);
#endif
    return (xsasl_status);
}
コード例 #5
0
static const char *xsasl_cyrus_server_get_username(XSASL_SERVER *xp)
{
    const char *myname = "xsasl_cyrus_server_get_username";
    XSASL_CYRUS_SERVER *server = (XSASL_CYRUS_SERVER *) xp;
    VOID_SERVEROUT_TYPE serverout = 0;
    int     sasl_status;

    /*
     * XXX Do not free(serverout).
     */
    sasl_status = sasl_getprop(server->sasl_conn, SASL_USERNAME, &serverout);
    if (sasl_status != SASL_OK || serverout == 0) {
	msg_warn("%s: sasl_getprop SASL_USERNAME botch: %s",
		 myname, xsasl_cyrus_strerror(sasl_status));
	return (0);
    }
    if (server->username)
	myfree(server->username);
    server->username = mystrdup(serverout);
    printable(server->username, '?');
    return (server->username);
}
コード例 #6
0
static int xsasl_cyrus_server_set_security(XSASL_SERVER *xp,
					           const char *sasl_opts_val)
{
    XSASL_CYRUS_SERVER *server = (XSASL_CYRUS_SERVER *) xp;
    sasl_security_properties_t sec_props;
    int     sasl_status;

    /*
     * Security options. Some information can be found in the sasl.h include
     * file.
     */
    memset(&sec_props, 0, sizeof(sec_props));
    sec_props.min_ssf = 0;
    sec_props.max_ssf = 0;			/* don't allow real SASL
						 * security layer */
    if (*sasl_opts_val == 0) {
	sec_props.security_flags = 0;
    } else {
	sec_props.security_flags =
	    xsasl_cyrus_security_parse_opts(sasl_opts_val);
	if (sec_props.security_flags == 0) {
	    msg_warn("bad per-session SASL security properties");
	    return (XSASL_AUTH_FAIL);
	}
    }
    sec_props.maxbufsize = 0;
    sec_props.property_names = 0;
    sec_props.property_values = 0;

    if ((sasl_status = sasl_setprop(server->sasl_conn, SASL_SEC_PROPS,
				    &sec_props)) != SASL_OK) {
	msg_warn("SASL per-connection security setup; %s",
		 xsasl_cyrus_strerror(sasl_status));
	return (XSASL_AUTH_FAIL);
    }
    return (XSASL_AUTH_OK);
}
コード例 #7
0
static int xsasl_cyrus_client_set_security(XSASL_CLIENT *xp,
					           const char *sasl_opts_val)
{
    XSASL_CYRUS_CLIENT *client = (XSASL_CYRUS_CLIENT *) xp;
    sasl_security_properties_t sec_props;
    int     sasl_status;

    /*
     * Per-session security properties. XXX This routine is not sufficiently
     * documented. What is the purpose of all this?
     */
    memset(&sec_props, 0, sizeof(sec_props));
    sec_props.min_ssf = 0;
    sec_props.max_ssf = 0;			/* don't allow real SASL
						 * security layer */
    if (*sasl_opts_val == 0) {
	sec_props.security_flags = 0;
    } else {
	sec_props.security_flags =
	    xsasl_cyrus_security_parse_opts(sasl_opts_val);
	if (sec_props.security_flags == 0) {
	    msg_warn("bad per-session SASL security properties");
	    return (XSASL_AUTH_FAIL);
	}
    }
    sec_props.maxbufsize = 0;
    sec_props.property_names = 0;
    sec_props.property_values = 0;
    if ((sasl_status = sasl_setprop(client->sasl_conn, SASL_SEC_PROPS,
				    &sec_props)) != SASL_OK) {
	msg_warn("set per-session SASL security properties: %s",
		 xsasl_cyrus_strerror(sasl_status));
	return (XSASL_AUTH_FAIL);
    }
    return (XSASL_AUTH_OK);
}
コード例 #8
0
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);
}
コード例 #9
0
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);
}
コード例 #10
0
XSASL_CLIENT *xsasl_cyrus_client_create(XSASL_CLIENT_IMPL *unused_impl,
				             XSASL_CLIENT_CREATE_ARGS *args)
{
    XSASL_CYRUS_CLIENT *client = 0;
    static sasl_callback_t callbacks[] = {
	{SASL_CB_USER, (XSASL_CYRUS_CB) &xsasl_cyrus_client_get_user, 0},
	{SASL_CB_AUTHNAME, (XSASL_CYRUS_CB) &xsasl_cyrus_client_get_user, 0},
	{SASL_CB_PASS, (XSASL_CYRUS_CB) &xsasl_cyrus_client_get_passwd, 0},
	{SASL_CB_LIST_END, 0, 0}
    };
    sasl_conn_t *sasl_conn = 0;
    sasl_callback_t *custom_callbacks = 0;
    sasl_callback_t *cp;
    int     sasl_status;

    /*
     * The optimizer will eliminate code duplication and/or dead code.
     */
#define XSASL_CYRUS_CLIENT_CREATE_ERROR_RETURN(x) \
    do { \
	if (client) { \
	    xsasl_cyrus_client_free(&client->xsasl); \
	} else { \
	    if (custom_callbacks) \
		myfree((void *) custom_callbacks); \
	    if (sasl_conn) \
		sasl_dispose(&sasl_conn); \
	} \
	return (x); \
    } while (0)

    /*
     * Per-session initialization. Provide each session with its own callback
     * context.
     */
#define NULL_SECFLAGS		0

    custom_callbacks = (sasl_callback_t *) mymalloc(sizeof(callbacks));
    memcpy((void *) custom_callbacks, callbacks, sizeof(callbacks));

#define NULL_SERVER_ADDR	((char *) 0)
#define NULL_CLIENT_ADDR	((char *) 0)

    if ((sasl_status = SASL_CLIENT_NEW(args->service, args->server_name,
				       NULL_CLIENT_ADDR, NULL_SERVER_ADDR,
				 var_cyrus_sasl_authzid ? custom_callbacks :
				       custom_callbacks + 1, NULL_SECFLAGS,
				       &sasl_conn)) != SASL_OK) {
	msg_warn("per-session SASL client initialization: %s",
		 xsasl_cyrus_strerror(sasl_status));
	XSASL_CYRUS_CLIENT_CREATE_ERROR_RETURN(0);
    }

    /*
     * Extend the XSASL_CLIENT object with our own state. We use long-lived
     * conversion buffers rather than local variables to avoid memory leaks
     * in case of read/write timeout or I/O error.
     * 
     * XXX If we enable SASL encryption, there needs to be a way to inform the
     * application, so that they can turn off connection caching, refuse
     * STARTTLS, etc.
     */
    client = (XSASL_CYRUS_CLIENT *) mymalloc(sizeof(*client));
    client->xsasl.free = xsasl_cyrus_client_free;
    client->xsasl.first = xsasl_cyrus_client_first;
    client->xsasl.next = xsasl_cyrus_client_next;
    client->stream = args->stream;
    client->sasl_conn = sasl_conn;
    client->callbacks = custom_callbacks;
    client->decoded = vstring_alloc(20);
    client->username = 0;
    client->password = 0;

    for (cp = custom_callbacks; cp->id != SASL_CB_LIST_END; cp++)
	cp->context = (void *) client;

    if (xsasl_cyrus_client_set_security(&client->xsasl,
					args->security_options)
	!= XSASL_AUTH_OK)
	XSASL_CYRUS_CLIENT_CREATE_ERROR_RETURN(0);

    return (&client->xsasl);
}
コード例 #11
0
XSASL_CLIENT_IMPL *xsasl_cyrus_client_init(const char *unused_client_type,
				               const char *unused_path_info)
{
    XSASL_CLIENT_IMPL *xp;
    int     sasl_status;

    /*
     * Global callbacks. These have no per-session context.
     */
    static sasl_callback_t callbacks[] = {
	{SASL_CB_LOG, (XSASL_CYRUS_CB) &xsasl_cyrus_log, 0},
	{SASL_CB_LIST_END, 0, 0}
    };

#if SASL_VERSION_MAJOR >= 2 && (SASL_VERSION_MINOR >= 2 \
    || (SASL_VERSION_MINOR == 1 && SASL_VERSION_STEP >= 19))
    int     sasl_major;
    int     sasl_minor;
    int     sasl_step;

    /*
     * DLL hell guard.
     */
    sasl_version_info((const char **) 0, (const char **) 0,
		      &sasl_major, &sasl_minor,
		      &sasl_step, (int *) 0);
    if (sasl_major != SASL_VERSION_MAJOR
#if 0
	|| sasl_minor != SASL_VERSION_MINOR
	|| sasl_step != SASL_VERSION_STEP
#endif
	) {
	msg_warn("incorrect SASL library version. "
	      "Postfix was built with include files from version %d.%d.%d, "
		 "but the run-time library version is %d.%d.%d",
		 SASL_VERSION_MAJOR, SASL_VERSION_MINOR, SASL_VERSION_STEP,
		 sasl_major, sasl_minor, sasl_step);
	return (0);
    }
#endif

    if (*var_cyrus_conf_path) {
#ifdef SASL_PATH_TYPE_CONFIG			/* Cyrus SASL 2.1.22 */
	if (sasl_set_path(SASL_PATH_TYPE_CONFIG,
			  var_cyrus_conf_path) != SASL_OK)
	    msg_warn("failed to set Cyrus SASL configuration path: \"%s\"",
		     var_cyrus_conf_path);
#else
	msg_warn("%s is not empty, but setting the Cyrus SASL configuration "
		 "path is not supported with SASL library version %d.%d.%d",
		 VAR_CYRUS_CONF_PATH, SASL_VERSION_MAJOR,
		 SASL_VERSION_MINOR, SASL_VERSION_STEP);
#endif
    }

    /*
     * Initialize the SASL library.
     */
    if ((sasl_status = sasl_client_init(callbacks)) != SASL_OK) {
	msg_warn("SASL library initialization error: %s",
		 xsasl_cyrus_strerror(sasl_status));
	return (0);
    }

    /*
     * Return a generic XSASL_CLIENT_IMPL object. We don't need to extend it
     * with our own methods or data.
     */
    xp = (XSASL_CLIENT_IMPL *) mymalloc(sizeof(*xp));
    xp->create = xsasl_cyrus_client_create;
    xp->done = xsasl_cyrus_client_done;
    return (xp);
}
コード例 #12
0
static XSASL_SERVER *xsasl_cyrus_server_create(XSASL_SERVER_IMPL *unused_impl,
				             XSASL_SERVER_CREATE_ARGS *args)
{
    const char *myname = "xsasl_cyrus_server_create";
    char   *server_address;
    char   *client_address;
    sasl_conn_t *sasl_conn = 0;
    XSASL_CYRUS_SERVER *server = 0;
    int     sasl_status;

    if (msg_verbose)
	msg_info("%s: SASL service=%s, realm=%s",
		 myname, args->service, args->user_realm ?
		 args->user_realm : "(null)");

    /*
     * The optimizer will eliminate code duplication and/or dead code.
     */
#define XSASL_CYRUS_SERVER_CREATE_ERROR_RETURN(x) \
    do { \
	if (server) { \
	    xsasl_cyrus_server_free(&server->xsasl); \
	} else { \
	    if (sasl_conn) \
		sasl_dispose(&sasl_conn); \
	} \
	return (x); \
    } while (0)

    /*
     * Set up a new server context.
     */
#define NO_SECURITY_LAYERS	(0)
#define NO_SESSION_CALLBACKS	((sasl_callback_t *) 0)
#define NO_AUTH_REALM		((char *) 0)

#if SASL_VERSION_MAJOR >= 2 && defined(USE_SASL_IP_AUTH)

    /*
     * Get IP addresses of local and remote endpoints for SASL.
     */
#error "USE_SASL_IP_AUTH is not implemented"

#else

    /*
     * Don't give any IP address information to SASL.  SASLv1 doesn't use it,
     * and in SASLv2 this will disable any mechanisms that do.
     */
    server_address = 0;
    client_address = 0;
#endif

    if ((sasl_status =
	 SASL_SERVER_NEW(args->service, var_myhostname,
			 args->user_realm ? args->user_realm : NO_AUTH_REALM,
			 server_address, client_address,
			 NO_SESSION_CALLBACKS, NO_SECURITY_LAYERS,
			 &sasl_conn)) != SASL_OK) {
	msg_warn("SASL per-connection server initialization: %s",
		 xsasl_cyrus_strerror(sasl_status));
	XSASL_CYRUS_SERVER_CREATE_ERROR_RETURN(0);
    }

    /*
     * Extend the XSASL_SERVER object with our own data. We use long-lived
     * conversion buffers rather than local variables to avoid memory leaks
     * in case of read/write timeout or I/O error.
     */
    server = (XSASL_CYRUS_SERVER *) mymalloc(sizeof(*server));
    server->xsasl.free = xsasl_cyrus_server_free;
    server->xsasl.first = xsasl_cyrus_server_first;
    server->xsasl.next = xsasl_cyrus_server_next;
    server->xsasl.get_mechanism_list = xsasl_cyrus_server_get_mechanism_list;
    server->xsasl.get_username = xsasl_cyrus_server_get_username;
    server->stream = args->stream;
    server->sasl_conn = sasl_conn;
    server->decoded = vstring_alloc(20);
    server->username = 0;
    server->mechanism_list = 0;

    if (xsasl_cyrus_server_set_security(&server->xsasl, args->security_options)
	!= XSASL_AUTH_OK)
	XSASL_CYRUS_SERVER_CREATE_ERROR_RETURN(0);

    return (&server->xsasl);
}
コード例 #13
0
XSASL_SERVER_IMPL *xsasl_cyrus_server_init(const char *unused_server_type,
					           const char *path_info)
{
    const char *myname = "xsasl_cyrus_server_init";
    XSASL_SERVER_IMPL *xp;
    int     sasl_status;

#if SASL_VERSION_MAJOR >= 2 && (SASL_VERSION_MINOR >= 2 \
    || (SASL_VERSION_MINOR == 1 && SASL_VERSION_STEP >= 19))
    int     sasl_major;
    int     sasl_minor;
    int     sasl_step;

    /*
     * DLL hell guard.
     */
    sasl_version_info((const char **) 0, (const char **) 0,
		      &sasl_major, &sasl_minor,
		      &sasl_step, (int *) 0);
    if (sasl_major != SASL_VERSION_MAJOR
#if 0
	|| sasl_minor != SASL_VERSION_MINOR
	|| sasl_step != SASL_VERSION_STEP
#endif
	) {
	msg_warn("incorrect SASL library version. "
	      "Postfix was built with include files from version %d.%d.%d, "
		 "but the run-time library version is %d.%d.%d",
		 SASL_VERSION_MAJOR, SASL_VERSION_MINOR, SASL_VERSION_STEP,
		 sasl_major, sasl_minor, sasl_step);
	return (0);
    }
#endif

    if (*var_cyrus_conf_path) {
#ifdef SASL_PATH_TYPE_CONFIG			/* Cyrus SASL 2.1.22 */
	if (sasl_set_path(SASL_PATH_TYPE_CONFIG,
			  var_cyrus_conf_path) != SASL_OK)
	    msg_warn("failed to set Cyrus SASL configuration path: \"%s\"",
		     var_cyrus_conf_path);
#else
	msg_warn("%s is not empty, but setting the Cyrus SASL configuration "
		 "path is not supported with SASL library version %d.%d.%d",
		 VAR_CYRUS_CONF_PATH, SASL_VERSION_MAJOR,
		 SASL_VERSION_MINOR, SASL_VERSION_STEP);
#endif
    }

    /*
     * Initialize the library: load SASL plug-in routines, etc.
     */
    if (msg_verbose)
	msg_info("%s: SASL config file is %s.conf", myname, path_info);
    if ((sasl_status = sasl_server_init(callbacks, path_info)) != SASL_OK) {
	msg_warn("SASL per-process initialization failed: %s",
		 xsasl_cyrus_strerror(sasl_status));
	return (0);
    }

    /*
     * Return a generic XSASL_SERVER_IMPL object. We don't need to extend it
     * with our own methods or data.
     */
    xp = (XSASL_SERVER_IMPL *) mymalloc(sizeof(*xp));
    xp->create = xsasl_cyrus_server_create;
    xp->done = xsasl_cyrus_server_done;
    return (xp);
}