⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 krbhst.c

📁 samba最新软件
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 2001 - 2003 Kungliga Tekniska H鰃skolan * (Royal Institute of Technology, Stockholm, Sweden).  * All rights reserved.  * * Redistribution and use in source and binary forms, with or without  * modification, are permitted provided that the following conditions  * are met:  * * 1. Redistributions of source code must retain the above copyright  *    notice, this list of conditions and the following disclaimer.  * * 2. Redistributions in binary form must reproduce the above copyright  *    notice, this list of conditions and the following disclaimer in the  *    documentation and/or other materials provided with the distribution.  * * 3. Neither the name of the Institute nor the names of its contributors  *    may be used to endorse or promote products derived from this software  *    without specific prior written permission.  * * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF  * SUCH DAMAGE.  */#include "krb5_locl.h"#include <resolve.h>#include "locate_plugin.h"RCSID("$Id: krbhst.c 21457 2007-07-10 12:53:25Z lha $");static intstring_to_proto(const char *string){    if(strcasecmp(string, "udp") == 0)	return KRB5_KRBHST_UDP;    else if(strcasecmp(string, "tcp") == 0) 	return KRB5_KRBHST_TCP;    else if(strcasecmp(string, "http") == 0) 	return KRB5_KRBHST_HTTP;    return -1;}/* * set `res' and `count' to the result of looking up SRV RR in DNS for * `proto', `proto', `realm' using `dns_type'. * if `port' != 0, force that port number */static krb5_error_codesrv_find_realm(krb5_context context, krb5_krbhst_info ***res, int *count, 	       const char *realm, const char *dns_type,	       const char *proto, const char *service, int port){    char domain[1024];    struct dns_reply *r;    struct resource_record *rr;    int num_srv;    int proto_num;    int def_port;    *res = NULL;    *count = 0;    proto_num = string_to_proto(proto);    if(proto_num < 0) {	krb5_set_error_string(context, "unknown protocol `%s'", proto);	return EINVAL;    }    if(proto_num == KRB5_KRBHST_HTTP)	def_port = ntohs(krb5_getportbyname (context, "http", "tcp", 80));    else if(port == 0)	def_port = ntohs(krb5_getportbyname (context, service, proto, 88));    else	def_port = port;    snprintf(domain, sizeof(domain), "_%s._%s.%s.", service, proto, realm);    r = dns_lookup(domain, dns_type);    if(r == NULL)	return KRB5_KDC_UNREACH;    for(num_srv = 0, rr = r->head; rr; rr = rr->next) 	if(rr->type == T_SRV)	    num_srv++;    *res = malloc(num_srv * sizeof(**res));    if(*res == NULL) {	dns_free_data(r);	krb5_set_error_string(context, "malloc: out of memory");	return ENOMEM;    }    dns_srv_order(r);    for(num_srv = 0, rr = r->head; rr; rr = rr->next) 	if(rr->type == T_SRV) {	    krb5_krbhst_info *hi;	    size_t len = strlen(rr->u.srv->target);	    hi = calloc(1, sizeof(*hi) + len);	    if(hi == NULL) {		dns_free_data(r);		while(--num_srv >= 0)		    free((*res)[num_srv]);		free(*res);		*res = NULL;		return ENOMEM;	    }	    (*res)[num_srv++] = hi;	    hi->proto = proto_num;	    	    hi->def_port = def_port;	    if (port != 0)		hi->port = port;	    else		hi->port = rr->u.srv->port;	    strlcpy(hi->hostname, rr->u.srv->target, len + 1);	}    *count = num_srv;	        dns_free_data(r);    return 0;}struct krb5_krbhst_data {    char *realm;    unsigned int flags;    int def_port;    int port;			/* hardwired port number if != 0 */#define KD_CONFIG		 1#define KD_SRV_UDP		 2#define KD_SRV_TCP		 4#define KD_SRV_HTTP		 8#define KD_FALLBACK		16#define KD_CONFIG_EXISTS	32#define KD_LARGE_MSG		64#define KD_PLUGIN	       128    krb5_error_code (*get_next)(krb5_context, struct krb5_krbhst_data *, 				krb5_krbhst_info**);    unsigned int fallback_count;    struct krb5_krbhst_info *hosts, **index, **end;};static krb5_booleankrbhst_empty(const struct krb5_krbhst_data *kd){    return kd->index == &kd->hosts;}/* * Return the default protocol for the `kd' (either TCP or UDP) */static intkrbhst_get_default_proto(struct krb5_krbhst_data *kd){    if (kd->flags & KD_LARGE_MSG)	return KRB5_KRBHST_TCP;    return KRB5_KRBHST_UDP;}/* * parse `spec' into a krb5_krbhst_info, defaulting the port to `def_port' * and forcing it to `port' if port != 0 */static struct krb5_krbhst_info*parse_hostspec(krb5_context context, struct krb5_krbhst_data *kd,	       const char *spec, int def_port, int port){    const char *p = spec;    struct krb5_krbhst_info *hi;        hi = calloc(1, sizeof(*hi) + strlen(spec));    if(hi == NULL)	return NULL;           hi->proto = krbhst_get_default_proto(kd);    if(strncmp(p, "http://", 7) == 0){	hi->proto = KRB5_KRBHST_HTTP;	p += 7;    } else if(strncmp(p, "http/", 5) == 0) {	hi->proto = KRB5_KRBHST_HTTP;	p += 5;	def_port = ntohs(krb5_getportbyname (context, "http", "tcp", 80));    }else if(strncmp(p, "tcp/", 4) == 0){	hi->proto = KRB5_KRBHST_TCP;	p += 4;    } else if(strncmp(p, "udp/", 4) == 0) {	p += 4;    }    if(strsep_copy(&p, ":", hi->hostname, strlen(spec) + 1) < 0) {	free(hi);	return NULL;    }    /* get rid of trailing /, and convert to lower case */    hi->hostname[strcspn(hi->hostname, "/")] = '\0';    strlwr(hi->hostname);    hi->port = hi->def_port = def_port;    if(p != NULL) {	char *end;	hi->port = strtol(p, &end, 0);	if(end == p) {	    free(hi);	    return NULL;	}    }    if (port)	hi->port = port;    return hi;}void_krb5_free_krbhst_info(krb5_krbhst_info *hi){    if (hi->ai != NULL)	freeaddrinfo(hi->ai);    free(hi);}krb5_error_code_krb5_krbhost_info_move(krb5_context context,			krb5_krbhst_info *from,			krb5_krbhst_info **to){    size_t hostnamelen = strlen(from->hostname);    /* trailing NUL is included in structure */    *to = calloc(1, sizeof(**to) + hostnamelen);     if(*to == NULL) {	krb5_set_error_string(context, "malloc - out of memory");	return ENOMEM;    }    (*to)->proto = from->proto;    (*to)->port = from->port;    (*to)->def_port = from->def_port;    (*to)->ai = from->ai;    from->ai = NULL;    (*to)->next = NULL;    memcpy((*to)->hostname, from->hostname, hostnamelen + 1);    return 0;}static voidappend_host_hostinfo(struct krb5_krbhst_data *kd, struct krb5_krbhst_info *host){    struct krb5_krbhst_info *h;    for(h = kd->hosts; h; h = h->next)	if(h->proto == host->proto && 	   h->port == host->port && 	   strcmp(h->hostname, host->hostname) == 0) {	    _krb5_free_krbhst_info(host);	    return;	}    *kd->end = host;    kd->end = &host->next;}static krb5_error_codeappend_host_string(krb5_context context, struct krb5_krbhst_data *kd,		   const char *host, int def_port, int port){    struct krb5_krbhst_info *hi;    hi = parse_hostspec(context, kd, host, def_port, port);    if(hi == NULL)	return ENOMEM;        append_host_hostinfo(kd, hi);    return 0;}/* * return a readable representation of `host' in `hostname, hostlen' */krb5_error_code KRB5_LIB_FUNCTIONkrb5_krbhst_format_string(krb5_context context, const krb5_krbhst_info *host, 			  char *hostname, size_t hostlen){    const char *proto = "";    char portstr[7] = "";    if(host->proto == KRB5_KRBHST_TCP)	proto = "tcp/";    else if(host->proto == KRB5_KRBHST_HTTP)	proto = "http://";    if(host->port != host->def_port)	snprintf(portstr, sizeof(portstr), ":%d", host->port);    snprintf(hostname, hostlen, "%s%s%s", proto, host->hostname, portstr);    return 0;}/* * create a getaddrinfo `hints' based on `proto' */static voidmake_hints(struct addrinfo *hints, int proto){    memset(hints, 0, sizeof(*hints));    hints->ai_family = AF_UNSPEC;    switch(proto) {    case KRB5_KRBHST_UDP :	hints->ai_socktype = SOCK_DGRAM;	break;    case KRB5_KRBHST_HTTP :    case KRB5_KRBHST_TCP :	hints->ai_socktype = SOCK_STREAM;	break;    }}/* * return an `struct addrinfo *' in `ai' corresponding to the information * in `host'.  free:ing is handled by krb5_krbhst_free. */krb5_error_code KRB5_LIB_FUNCTIONkrb5_krbhst_get_addrinfo(krb5_context context, krb5_krbhst_info *host,			 struct addrinfo **ai){    struct addrinfo hints;    char portstr[NI_MAXSERV];    int ret;    if (host->ai == NULL) {	make_hints(&hints, host->proto);	snprintf (portstr, sizeof(portstr), "%d", host->port);	ret = getaddrinfo(host->hostname, portstr, &hints, &host->ai);	if (ret)	    return krb5_eai_to_heim_errno(ret, errno);    }    *ai = host->ai;    return 0;}static krb5_booleanget_next(struct krb5_krbhst_data *kd, krb5_krbhst_info **host){    struct krb5_krbhst_info *hi = *kd->index;    if(hi != NULL) {	*host = hi;	kd->index = &(*kd->index)->next;	return TRUE;    }    return FALSE;}static voidsrv_get_hosts(krb5_context context, struct krb5_krbhst_data *kd, 	      const char *proto, const char *service){    krb5_krbhst_info **res;    int count, i;    if (srv_find_realm(context, &res, &count, kd->realm, "SRV", proto, service,		       kd->port))	return;    for(i = 0; i < count; i++)	append_host_hostinfo(kd, res[i]);    free(res);}/* * read the configuration for `conf_string', defaulting to kd->def_port and * forcing it to `kd->port' if kd->port != 0 */static voidconfig_get_hosts(krb5_context context, struct krb5_krbhst_data *kd, 		 const char *conf_string){    int i;	    char **hostlist;    hostlist = krb5_config_get_strings(context, NULL, 				       "realms", kd->realm, conf_string, NULL);    if(hostlist == NULL)	return;    kd->flags |= KD_CONFIG_EXISTS;    for(i = 0; hostlist && hostlist[i] != NULL; i++)	append_host_string(context, kd, hostlist[i], kd->def_port, kd->port);    krb5_config_free_strings(hostlist);}/* * as a fallback, look for `serv_string.kd->realm' (typically * kerberos.REALM, kerberos-1.REALM, ... * `port' is the default port for the service, and `proto' the  * protocol */static krb5_error_codefallback_get_hosts(krb5_context context, struct krb5_krbhst_data *kd, 		   const char *serv_string, int port, int proto){    char *host;    int ret;    struct addrinfo *ai;    struct addrinfo hints;    char portstr[NI_MAXSERV];    /*      * Don't try forever in case the DNS server keep returning us     * entries (like wildcard entries or the .nu TLD)     */    if(kd->fallback_count >= 5) {	kd->flags |= KD_FALLBACK;	return 0;    }    if(kd->fallback_count == 0)	asprintf(&host, "%s.%s.", serv_string, kd->realm);    else	asprintf(&host, "%s-%d.%s.", 		 serv_string, kd->fallback_count, kd->realm);	        if (host == NULL)	return ENOMEM;        make_hints(&hints, proto);    snprintf(portstr, sizeof(portstr), "%d", port);    ret = getaddrinfo(host, portstr, &hints, &ai);    if (ret) {	/* no more hosts, so we're done here */	free(host);	kd->flags |= KD_FALLBACK;    } else {	struct krb5_krbhst_info *hi;	size_t hostlen = strlen(host);	hi = calloc(1, sizeof(*hi) + hostlen);	if(hi == NULL) {	    free(host);	    return ENOMEM;	}	hi->proto = proto;	hi->port  = hi->def_port = port;	hi->ai    = ai;	memmove(hi->hostname, host, hostlen);	hi->hostname[hostlen] = '\0';	free(host);	append_host_hostinfo(kd, hi);	kd->fallback_count++;    }    return 0;}/* * Fetch hosts from plugin */static krb5_error_code add_locate(void *ctx, int type, struct sockaddr *addr){    struct krb5_krbhst_info *hi;    struct krb5_krbhst_data *kd = ctx;    char host[NI_MAXHOST], port[NI_MAXSERV];    struct addrinfo hints, *ai;    socklen_t socklen;    size_t hostlen;    int ret;    socklen = socket_sockaddr_size(addr);    ret = getnameinfo(addr, socklen, host, sizeof(host), port, sizeof(port),		      NI_NUMERICHOST|NI_NUMERICSERV);    if (ret != 0)	return 0;    make_hints(&hints, krbhst_get_default_proto(kd));    ret = getaddrinfo(host, port, &hints, &ai);    if (ret)	return 0;    hostlen = strlen(host);    hi = calloc(1, sizeof(*hi) + hostlen);    if(hi == NULL)	return ENOMEM;    

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -