/* * Given the list of hostnames of KDCs found in DNS SRV recs, lets go * thru NSS (name svc switch) to get the net addrs. */ static krb5_error_code dns_hostnames2netaddrs( struct srv_dns_entry *head, enum locate_service_type svc, int socktype, int family, struct addrlist *addrlist) { struct srv_dns_entry *entry = NULL, *next; krb5_error_code code; Tprintf ("walking answer list:\n"); for (entry = head; entry != NULL; entry = entry->next) { code = 0; if (socktype) code = add_host_to_list (addrlist, entry->host, htons (entry->port), 0, socktype, family); else { (void) add_host_to_list (addrlist, entry->host, htons (entry->port), 0, SOCK_DGRAM, family); code = add_host_to_list (addrlist, entry->host, htons (entry->port), 0, SOCK_STREAM, family); } if (code) { Tprintf(" fail add_host code=%d %s\n", code, entry->host); } } Tprintf ("[end]\n"); return code; }
static krb5_error_code locate_srv_dns_1(const krb5_data *realm, const char *service, const char *protocol, struct serverlist *serverlist) { struct srv_dns_entry *head = NULL, *entry = NULL; krb5_error_code code = 0; int socktype; code = krb5int_make_srv_query_realm(realm, service, protocol, &head); if (code) return 0; if (head == NULL) return 0; /* Check for the "." case indicating no support. */ if (head->next == NULL && head->host[0] == '\0') { code = KRB5_ERR_NO_SERVICE; goto cleanup; } for (entry = head; entry != NULL; entry = entry->next) { socktype = (strcmp(protocol, "_tcp") == 0) ? SOCK_STREAM : SOCK_DGRAM; code = add_host_to_list(serverlist, entry->host, htons(entry->port), socktype, AF_UNSPEC); if (code) goto cleanup; } cleanup: krb5int_free_srv_dns_data(head); return code; }
static krb5_error_code locate_srv_dns_1(krb5_context context, const krb5_data *realm, const char *service, const char *protocol, struct serverlist *serverlist) { struct srv_dns_entry *head = NULL, *entry = NULL; krb5_error_code code = 0; k5_transport transport; code = krb5int_make_srv_query_realm(context, realm, service, protocol, &head); if (code) return 0; if (head == NULL) return 0; /* Check for the "." case indicating no support. */ if (head->next == NULL && head->host[0] == '\0') { code = KRB5_ERR_NO_SERVICE; goto cleanup; } for (entry = head; entry != NULL; entry = entry->next) { transport = (strcmp(protocol, "_tcp") == 0) ? TCP : UDP; code = add_host_to_list(serverlist, entry->host, entry->port, transport, AF_UNSPEC, NULL, -1); if (code) goto cleanup; } cleanup: krb5int_free_srv_dns_data(head); return code; }
/* * Collect a list of servers from DNS URI records, for the requested service * and transport type. Problematic entries are skipped. */ static krb5_error_code locate_uri(krb5_context context, const krb5_data *realm, const char *req_service, struct serverlist *serverlist, k5_transport req_transport, int default_port, krb5_boolean master_only) { krb5_error_code ret; k5_transport transport, host_trans; struct srv_dns_entry *answers, *entry; char *host; const char *host_field, *path; int port, def_port, master; ret = k5_make_uri_query(context, realm, req_service, &answers); if (ret || answers == NULL) return ret; for (entry = answers; entry != NULL; entry = entry->next) { def_port = default_port; path = NULL; parse_uri_fields(entry->host, &transport, &host_field, &master); if (host_field == NULL) continue; /* TCP_OR_UDP allows entries of any transport type; otherwise * we're asking for a match. */ if (req_transport != TCP_OR_UDP && req_transport != transport) continue; /* Process a MS-KKDCP target. */ if (transport == HTTPS) { host_trans = 0; def_port = 443; parse_uri_if_https(host_field, &host_trans, &host_field, &path); if (host_trans != HTTPS) continue; } ret = k5_parse_host_string(host_field, def_port, &host, &port); if (ret == ENOMEM) break; if (ret || host == NULL) { ret = 0; continue; } ret = add_host_to_list(serverlist, host, port, transport, AF_UNSPEC, path, master); free(host); if (ret) break; } krb5int_free_srv_dns_data(answers); return ret; }
void add_hosts_in_subnet_to_list(char *ipsubnet) { char *ipaddr = cl_malloc(strlen(ipsubnet) + 4); /* 3 digits, NUL */ int i; for (i = 1; i <= 255; i++) { sprintf(ipaddr, "%s%d", ipsubnet, i); add_host_to_list(ipaddr); } cl_free(ipaddr); }
/* * Take the profile KDC list and return a list of net addrs. */ static krb5_error_code prof_hostnames2netaddrs( char **hostlist, enum locate_service_type svc, int socktype, int family, struct addrlist *addrlist) /* output */ { int udpport = 0 , sec_udpport = 0; int code, i; struct servent *serv; int count = 0; while (hostlist && hostlist[count]) count++; if (count == 0) { return 0; } switch (svc) { case locate_service_kdc: case locate_service_master_kdc: /* We used to use /etc/services for these, but enough systems have old, crufty, wrong settings that this is probably better. */ udpport = htons(KRB5_DEFAULT_PORT); sec_udpport = htons(KRB5_DEFAULT_SEC_PORT); break; case locate_service_kadmin: udpport = htons(DEFAULT_KADM5_PORT); break; case locate_service_krb524: serv = getservbyname(KRB524_SERVICE, "udp"); udpport = serv ? serv->s_port : htons (KRB524_PORT); break; case locate_service_kpasswd: udpport = htons(DEFAULT_KPASSWD_PORT); break; default: return EINVAL; } for (i=0; hostlist[i]; i++) { int p1, p2; char *cp, *port, *host; host = hostlist[i]; /* * Strip off excess whitespace */ cp = strchr(host, ' '); if (cp) *cp = 0; cp = strchr(host, '\t'); if (cp) *cp = 0; port = strchr(host, ':'); if (port) { *port = 0; port++; } if (port) { unsigned long l; #ifdef HAVE_STROUL char *endptr; l = strtoul (port, &endptr, 10); if (endptr == NULL || *endptr != 0) return EINVAL; #else l = atoi (port); #endif /* L is unsigned, don't need to check <0. */ if (l == 0 || l > 65535) return EINVAL; p1 = htons (l); p2 = 0; } else { p1 = udpport; p2 = sec_udpport; } if (socktype != 0) { code = add_host_to_list (addrlist, hostlist[i], p1, p2, socktype, family); } else { code = add_host_to_list (addrlist, hostlist[i], p1, p2, SOCK_DGRAM, family); if (code == 0) code = add_host_to_list (addrlist, hostlist[i], p1, p2, SOCK_STREAM, family); } } return code; }
/** * Main function for the cqpserver app. */ int main(int argc, char *argv[]) { int cmd; which_app = cqpserver; /* TODO: shouldn't these come AFTER initialize_cqp(), as that function may overwrite these values with defaults? * or maybe I've missed some subtlety here....*/ silent = 1; paging = autoshow = auto_save = 0; if (!initialize_cqp(argc, argv)) { Rprintf( "CQPserver: ERROR Couldn't initialise CQP engine.\n"); rcqp_receive_error(1); } cqiserver_welcome(); if (localhost) { add_host_to_list("127.0.0.1"); /* in -L mode, connections from localhost are automatically accepted */ } if (0 < accept_connection(server_port)) { if (server_log) Rprintf("CQPserver: Connected. Waiting for CONNECT request.\n"); } else { Rprintf( "CQPserver: ERROR Connection failed.\n"); rcqp_receive_error(1); } /* establish CQi connection: wait for CONNECT request */ cmd = cqi_read_command(); if (cmd != CQI_CTRL_CONNECT) { if (server_log) Rprintf("CQPserver: Connection refused.\n"); cqiserver_wrong_command_error(cmd); } user = cqi_read_string(); passwd = cqi_read_string(); if (server_log) Rprintf("CQPserver: CONNECT user = '******' passwd = '%s' pid = %d\n", user, passwd, (int)getpid()); /* check password here (always required !!) */ if (!authenticate_user(user, passwd)) { Rprintf("CQPserver: Wrong username or password. Connection refused.\n"); /* TODO shouldn't this be to stderr as it is not conditional on server_log? */ cqi_command(CQI_ERROR_CONNECT_REFUSED); } else { cqi_command(CQI_STATUS_CONNECT_OK); /* re-randomize for query lock key generation */ cl_randomize(); /* check which corpora the user is granted access to */ { CorpusList *cl = FirstCorpusFromList(); while (cl != NULL) { if (!check_grant(user, cl->name)) dropcorpus(cl); cl = NextCorpusFromList(cl); } } /* start command interpreter loop */ interpreter(); if (server_log) Rprintf("CQPserver: User '%s' has logged off.\n", user); } /* connection terminated; clean up and exit */ Rprintf("CQPserver: Exit. (pid = %d)\n", (int)getpid()); /* TODO should we check cqp_error_status as in the main cqp app? */ return 0; }
static krb5_error_code locate_srv_conf_1(krb5_context context, const krb5_data *realm, const char * name, struct serverlist *serverlist, int socktype, int udpport, int sec_udpport) { const char *realm_srv_names[4]; char **hostlist, *host, *port, *cp; krb5_error_code code; int i; Tprintf ("looking in krb5.conf for realm %s entry %s; ports %d,%d\n", realm->data, name, ntohs (udpport), ntohs (sec_udpport)); if ((host = malloc(realm->length + 1)) == NULL) return ENOMEM; strncpy(host, realm->data, realm->length); host[realm->length] = '\0'; hostlist = 0; realm_srv_names[0] = KRB5_CONF_REALMS; realm_srv_names[1] = host; realm_srv_names[2] = name; realm_srv_names[3] = 0; code = profile_get_values(context->profile, realm_srv_names, &hostlist); free(host); if (code) { Tprintf ("config file lookup failed: %s\n", error_message(code)); if (code == PROF_NO_SECTION || code == PROF_NO_RELATION) code = 0; return code; } for (i=0; hostlist[i]; i++) { int p1, p2; host = hostlist[i]; Tprintf ("entry %d is '%s'\n", i, host); /* Find port number, and strip off any excess characters. */ if (*host == '[' && (cp = strchr(host, ']'))) cp = cp + 1; else cp = host + strcspn(host, " \t:"); port = (*cp == ':') ? cp + 1 : NULL; *cp = '\0'; if (port) { unsigned long l; #ifdef HAVE_STROUL char *endptr; l = strtoul (port, &endptr, 10); if (endptr == NULL || *endptr != 0) return EINVAL; #else l = atoi (port); #endif /* L is unsigned, don't need to check <0. */ if (l > 65535) return EINVAL; p1 = htons (l); p2 = 0; } else { p1 = udpport; p2 = sec_udpport; } /* If the hostname was in brackets, strip those off now. */ if (*host == '[' && (cp = strchr(host, ']'))) { host++; *cp = '\0'; } code = add_host_to_list(serverlist, host, p1, socktype, AF_UNSPEC); /* Second port is for IPv4 UDP only, and should possibly go away as * it was originally a krb4 compatibility measure. */ if (code == 0 && p2 != 0 && (socktype == 0 || socktype == SOCK_DGRAM)) code = add_host_to_list(serverlist, host, p2, SOCK_DGRAM, AF_INET); if (code) goto cleanup; } cleanup: profile_free_list(hostlist); return code; }
static krb5_error_code locate_srv_conf_1(krb5_context context, const krb5_data *realm, const char * name, struct serverlist *serverlist, k5_transport transport, int udpport) { const char *realm_srv_names[4]; char **hostlist = NULL, *realmstr = NULL, *host = NULL; const char *hostspec; krb5_error_code code; int i, default_port; Tprintf("looking in krb5.conf for realm %s entry %s; ports %d,%d\n", realm->data, name, udpport); realmstr = k5memdup0(realm->data, realm->length, &code); if (realmstr == NULL) goto cleanup; realm_srv_names[0] = KRB5_CONF_REALMS; realm_srv_names[1] = realmstr; realm_srv_names[2] = name; realm_srv_names[3] = 0; code = profile_get_values(context->profile, realm_srv_names, &hostlist); if (code) { Tprintf("config file lookup failed: %s\n", error_message(code)); if (code == PROF_NO_SECTION || code == PROF_NO_RELATION) code = 0; goto cleanup; } for (i = 0; hostlist[i]; i++) { int port_num; k5_transport this_transport = transport; const char *uri_path = NULL; hostspec = hostlist[i]; Tprintf("entry %d is '%s'\n", i, hostspec); parse_uri_if_https(hostspec, &this_transport, &hostspec, &uri_path); default_port = (this_transport == HTTPS) ? 443 : udpport; code = k5_parse_host_string(hostspec, default_port, &host, &port_num); if (code == 0 && host == NULL) code = EINVAL; if (code) goto cleanup; code = add_host_to_list(serverlist, host, port_num, this_transport, AF_UNSPEC, uri_path, -1); if (code) goto cleanup; free(host); host = NULL; } cleanup: free(realmstr); free(host); profile_free_list(hostlist); return code; }