Ejemplo n.º 1
0
static int xsasl_dovecot_server_connect(XSASL_DOVECOT_SERVER_IMPL *xp)
{
    const char *myname = "xsasl_dovecot_server_connect";
    VSTRING *line_str;
    VSTREAM *sasl_stream;
    char   *line, *cmd, *mech_name;
    unsigned int major_version, minor_version;
    int     fd, success;
    int     sec_props;
    const char *path;

    if (msg_verbose)
	msg_info("%s: Connecting", myname);

    /*
     * Not documented, but necessary for testing.
     */
    path = xp->socket_path;
    if (strncmp(path, "inet:", 5) == 0) {
	fd = inet_connect(path + 5, BLOCKING, AUTH_TIMEOUT);
    } else {
	if (strncmp(path, "unix:", 5) == 0)
	    path += 5;
	fd = unix_connect(path, BLOCKING, AUTH_TIMEOUT);
    }
    if (fd < 0) {
	msg_warn("SASL: Connect to %s failed: %m", xp->socket_path);
	return (-1);
    }
    sasl_stream = vstream_fdopen(fd, O_RDWR);
    vstream_control(sasl_stream,
		    VSTREAM_CTL_PATH, xp->socket_path,
		    VSTREAM_CTL_TIMEOUT, AUTH_TIMEOUT,
		    VSTREAM_CTL_END);

    /* XXX Encapsulate for logging. */
    vstream_fprintf(sasl_stream,
		    "VERSION\t%u\t%u\n"
		    "CPID\t%u\n",
		    AUTH_PROTOCOL_MAJOR_VERSION,
		    AUTH_PROTOCOL_MINOR_VERSION,
		    (unsigned int) getpid());
    if (vstream_fflush(sasl_stream) == VSTREAM_EOF) {
	msg_warn("SASL: Couldn't send handshake: %m");
	return (-1);
    }
    success = 0;
    line_str = vstring_alloc(256);
    /* XXX Encapsulate for logging. */
    while (vstring_get_nonl(line_str, sasl_stream) != VSTREAM_EOF) {
	line = vstring_str(line_str);

	if (msg_verbose)
	    msg_info("%s: auth reply: %s", myname, line);

	cmd = line;
	line = split_at(line, '\t');

	if (strcmp(cmd, "VERSION") == 0) {
	    if (sscanf(line, "%u\t%u", &major_version, &minor_version) != 2) {
		msg_warn("SASL: Protocol version error");
		break;
	    }
	    if (major_version != AUTH_PROTOCOL_MAJOR_VERSION) {
		/* Major version is different from ours. */
		msg_warn("SASL: Protocol version mismatch (%d vs. %d)",
			 major_version, AUTH_PROTOCOL_MAJOR_VERSION);
		break;
	    }
	} else if (strcmp(cmd, "MECH") == 0 && line != NULL) {
	    mech_name = line;
	    line = split_at(line, '\t');
	    if (line != 0) {
		sec_props =
		    name_mask_delim_opt(myname,
					xsasl_dovecot_serv_sec_props,
					line, "\t",
				     NAME_MASK_ANY_CASE | NAME_MASK_IGNORE);
		if ((sec_props & SEC_PROPS_PRIVATE) != 0)
		    continue;
	    } else
		sec_props = 0;
	    xsasl_dovecot_server_mech_append(&xp->mechanism_list, mech_name,
					     sec_props);
	} else if (strcmp(cmd, "DONE") == 0) {
	    /* Handshake finished. */
	    success = 1;
	    break;
	} else {
	    /* ignore any unknown commands */
	}
    }
    vstring_free(line_str);

    if (!success) {
	/* handshake failed */
	(void) vstream_fclose(sasl_stream);
	return (-1);
    }
    xp->sasl_stream = sasl_stream;
    return (0);
}
Ejemplo n.º 2
0
static int xsasl_dovecot_server_connect(XSASL_DOVECOT_SERVER_IMPL *xp)
{
    const char *myname = "xsasl_dovecot_server_connect";
    VSTRING *line_str;
    VSTREAM *sasl_stream;
    char   *line, *cmd, *mech_name;
    unsigned int major_version, minor_version;
    int     fd, success, have_mech_line;
    int     sec_props;
    const char *path;

    if (msg_verbose)
	msg_info("%s: Connecting", myname);

    /*
     * Not documented, but necessary for testing.
     */
    path = xp->socket_path;
    if (strncmp(path, "inet:", 5) == 0) {
	fd = inet_connect(path + 5, BLOCKING, AUTH_TIMEOUT);
    } else {
	if (strncmp(path, "unix:", 5) == 0)
	    path += 5;
	fd = unix_connect(path, BLOCKING, AUTH_TIMEOUT);
    }
    if (fd < 0) {
	msg_warn("SASL: Connect to %s failed: %m", xp->socket_path);
	return (-1);
    }
    sasl_stream = vstream_fdopen(fd, O_RDWR);
    vstream_control(sasl_stream,
		    CA_VSTREAM_CTL_PATH(xp->socket_path),
		    CA_VSTREAM_CTL_TIMEOUT(AUTH_TIMEOUT),
		    CA_VSTREAM_CTL_END);

    /* XXX Encapsulate for logging. */
    vstream_fprintf(sasl_stream,
		    "VERSION\t%u\t%u\n"
		    "CPID\t%u\n",
		    AUTH_PROTOCOL_MAJOR_VERSION,
		    AUTH_PROTOCOL_MINOR_VERSION,
		    (unsigned int) getpid());
    if (vstream_fflush(sasl_stream) == VSTREAM_EOF) {
	msg_warn("SASL: Couldn't send handshake: %m");
	return (-1);
    }
    success = 0;
    have_mech_line = 0;
    line_str = vstring_alloc(256);
    /* XXX Encapsulate for logging. */
    while (vstring_get_nonl(line_str, sasl_stream) != VSTREAM_EOF) {
	line = vstring_str(line_str);

	if (msg_verbose)
	    msg_info("%s: auth reply: %s", myname, line);

	cmd = line;
	line = split_at(line, '\t');

	if (strcmp(cmd, "VERSION") == 0) {
	    if (sscanf(line, "%u\t%u", &major_version, &minor_version) != 2) {
		msg_warn("SASL: Protocol version error");
		break;
	    }
	    if (major_version != AUTH_PROTOCOL_MAJOR_VERSION) {
		/* Major version is different from ours. */
		msg_warn("SASL: Protocol version mismatch (%d vs. %d)",
			 major_version, AUTH_PROTOCOL_MAJOR_VERSION);
		break;
	    }
	} else if (strcmp(cmd, "MECH") == 0 && line != NULL) {
	    mech_name = line;
	    have_mech_line = 1;
	    line = split_at(line, '\t');
	    if (line != 0) {
		sec_props =
		    name_mask_delim_opt(myname,
					xsasl_dovecot_serv_sec_props,
					line, "\t",
				     NAME_MASK_ANY_CASE | NAME_MASK_IGNORE);
		if ((sec_props & SEC_PROPS_PRIVATE) != 0)
		    continue;
	    } else
		sec_props = 0;
	    xsasl_dovecot_server_mech_append(&xp->mechanism_list, mech_name,
					     sec_props);
	} else if (strcmp(cmd, "SPID") == 0) {

	    /*
	     * Unfortunately the auth protocol handshake wasn't designed well
	     * to differentiate between auth-client/userdb/master.
	     * auth-userdb and auth-master send VERSION + SPID lines only and
	     * nothing afterwards, while auth-client sends VERSION + MECH +
	     * SPID + CUID + more. The simplest way that we can determine if
	     * we've connected to the correct socket is to see if MECH line
	     * exists or not (alternatively we'd have to have a small timeout
	     * after SPID to see if CUID is sent or not).
	     */
	    if (!have_mech_line) {
		msg_warn("SASL: Connected to wrong auth socket (auth-master instead of auth-client)");
		break;
	    }
	} else if (strcmp(cmd, "DONE") == 0) {
	    /* Handshake finished. */
	    success = 1;
	    break;
	} else {
	    /* ignore any unknown commands */
	}
    }
    vstring_free(line_str);

    if (!success) {
	/* handshake failed */
	(void) vstream_fclose(sasl_stream);
	return (-1);
    }
    xp->sasl_stream = sasl_stream;
    return (0);
}
Ejemplo n.º 3
0
static int strategy_from_string(const char *strategy_string)
{
    return (name_mask_delim_opt("strategy_from_string", strategy_table,
				strategy_string, "|",
				NAME_MASK_WARN | NAME_MASK_ANY_CASE));
}