Пример #1
0
/* Incomplete implementation, single ipv4 addr, service does not work, hints do not work */
int
tds_getaddrinfo(const char *node, const char *service, const struct tds_addrinfo *hints, struct tds_addrinfo **res)
{
    struct tds_addrinfo *addr;
    struct sockaddr_in *sin = NULL;
    struct hostent *host;
    in_addr_t ipaddr;
    char buffer[4096];
    struct hostent result;
    int h_errnop, port = 0;

    assert(node != NULL);

    if ((addr = (tds_addrinfo *) calloc(1, sizeof(struct tds_addrinfo))) == NULL)
        goto Cleanup;

    if ((sin = (struct sockaddr_in *) calloc(1, sizeof(struct sockaddr_in))) == NULL)
        goto Cleanup;

    addr->ai_addr = (struct sockaddr *) sin;
    addr->ai_addrlen = sizeof(struct sockaddr_in);
    addr->ai_family = AF_INET;

    if ((ipaddr = inet_addr(node)) == INADDR_NONE) {
        if ((host = tds_gethostbyname_r(node, &result, buffer, sizeof(buffer), &h_errnop)) == NULL)
            goto Cleanup;
        if (host->h_name)
            addr->ai_canonname = strdup(host->h_name);
        ipaddr = *(in_addr_t *) host->h_addr;
    }

    if (service) {
        port = atoi(service);
        if (!port)
            port = tds_getservice(service);
    }

    sin->sin_family = AF_INET;
    sin->sin_addr.s_addr = ipaddr;
    sin->sin_port = htons(port);

    *res = addr;
    return 0;

Cleanup:
    if (addr != NULL)
        tds_freeaddrinfo(addr);

    return -1;
}
Пример #2
0
TDSRET
tds_lookup_host_set(const char *servername, struct tds_addrinfo **addr)
{
	struct tds_addrinfo *newaddr;
	assert(servername != NULL && addr != NULL);

	if ((newaddr = tds_lookup_host(servername)) != NULL) {
		if (*addr != NULL)
			tds_freeaddrinfo(*addr);
		*addr = newaddr;
		return TDS_SUCCESS;
	}
	return TDS_FAIL;
}
Пример #3
0
/**
 * Build a GSSAPI packet to send to server
 * @param tds     A pointer to the TDSSOCKET structure managing a client/server operation.
 * @param packet  GSSAPI packet build from function
 * @return size of packet
 */
TDSAUTHENTICATION * 
tds_gss_get_auth(TDSSOCKET * tds)
{
	/*
	 * TODO
	 * There are some differences between this implementation and MS on
	 * - MS use SPNEGO with 3 mechnisms (MS KRB5, KRB5, NTLMSSP)
	 * - MS seems to use MUTUAL flag
	 * - name type is "Service and Instance (2)" and not "Principal (1)"
	 * check for memory leaks
	 * check for errors in many functions
	 * a bit more verbose
	 * dinamically load library ??
	 */
	gss_buffer_desc send_tok;
	OM_uint32 maj_stat, min_stat;
	/* same as GSS_KRB5_NT_PRINCIPAL_NAME but do not require .so library */
	static gss_OID_desc nt_principal = { 10, (void*) "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x01" };
	const char *server_name;
	/* Storage for getaddrinfo calls */
	struct tds_addrinfo *addrs = NULL;

	struct tds_gss_auth *auth = (struct tds_gss_auth *) calloc(1, sizeof(struct tds_gss_auth));

	if (!auth || !tds->login)
		return NULL;

	auth->tds_auth.free = tds_gss_free;
	auth->tds_auth.handle_next = tds_gss_handle_next;
	auth->gss_context = GSS_C_NO_CONTEXT;
	auth->last_stat = GSS_S_COMPLETE;

	server_name = tds_dstr_cstr(&tds->login->server_host_name);
	if (strchr(server_name, '.') == NULL) {
		struct tds_addrinfo hints;
		memset(&hints, 0, sizeof(hints));
		hints.ai_family = AF_UNSPEC;
		hints.ai_flags = AI_V4MAPPED|AI_ADDRCONFIG|AI_CANONNAME|AI_FQDN;
		if (!tds_getaddrinfo(server_name, NULL, &hints, &addrs) && addrs->ai_canonname
		    && strchr(addrs->ai_canonname, '.') != NULL)
			server_name = addrs->ai_canonname;
	}

	if (!tds_dstr_isempty(&tds->login->server_spn)) {
		auth->sname = strdup(tds_dstr_cstr(&tds->login->server_spn));
	} else if (tds_dstr_isempty(&tds->login->server_realm_name)) {
		if (asprintf(&auth->sname, "MSSQLSvc/%s:%d", server_name, tds->login->port) < 0)
			auth->sname = NULL;
	} else {
		if (asprintf(&auth->sname, "MSSQLSvc/%s:%d@%s", server_name, tds->login->port,
		             tds_dstr_cstr(&tds->login->server_realm_name)) < 0)
			auth->sname = NULL;
	}
	if (addrs)
		tds_freeaddrinfo(addrs);
	if (auth->sname == NULL) {
		tds_gss_free(tds->conn, (TDSAUTHENTICATION *) auth);
		return NULL;
	}
	tdsdump_log(TDS_DBG_NETWORK, "using kerberos name %s\n", auth->sname);

	/*
	 * Import the name into target_name.  Use send_tok to save
	 * local variable space.
	 */
	send_tok.value = auth->sname;
	send_tok.length = strlen(auth->sname);
	maj_stat = gss_import_name(&min_stat, &send_tok, &nt_principal, &auth->target_name);

	switch (maj_stat) {
	case GSS_S_COMPLETE: 
		tdsdump_log(TDS_DBG_NETWORK, "gss_import_name: GSS_S_COMPLETE: gss_import_name completed successfully.\n");
		if (TDS_FAILED(tds_gss_continue(tds, auth, GSS_C_NO_BUFFER))) {
			tds_gss_free(tds->conn, (TDSAUTHENTICATION *) auth);
			return NULL;
		}
		break;
	case GSS_S_BAD_NAMETYPE: 
		tdsdump_log(TDS_DBG_NETWORK, "gss_import_name: GSS_S_BAD_NAMETYPE: The input_name_type was unrecognized.\n");
		break;
	case GSS_S_BAD_NAME: 
		tdsdump_log(TDS_DBG_NETWORK, "gss_import_name: GSS_S_BAD_NAME: The input_name parameter could not be interpreted as a name of the specified type.\n");
		break;
	case GSS_S_BAD_MECH:
		tdsdump_log(TDS_DBG_NETWORK, "gss_import_name: GSS_S_BAD_MECH: The input name-type was GSS_C_NT_EXPORT_NAME, but the mechanism contained within the input-name is not supported.\n");
		break;
	default:
		tdsdump_log(TDS_DBG_NETWORK, "gss_import_name: unexpected error %d.\n", maj_stat);
		break;
	}

	if (GSS_ERROR(maj_stat)) {
		tds_gss_free(tds->conn, (TDSAUTHENTICATION *) auth);
		return NULL;
	}

	return (TDSAUTHENTICATION *) auth;
}