diff options
author | Greg Hudson <ghudson@mit.edu> | 2010-06-26 03:32:55 +0000 |
---|---|---|
committer | Greg Hudson <ghudson@mit.edu> | 2010-06-26 03:32:55 +0000 |
commit | 0080380b3b3e945c5eb84504771d9d01ee76a611 (patch) | |
tree | 39234f0c55f0a9304b935e0f38c7c9b14aa0c7cf /src/lib/kadm5 | |
parent | 5191e163a9a39ae11e1e62f4a2e191f2d26fbb7a (diff) | |
download | krb5-0080380b3b3e945c5eb84504771d9d01ee76a611.zip krb5-0080380b3b3e945c5eb84504771d9d01ee76a611.tar.gz krb5-0080380b3b3e945c5eb84504771d9d01ee76a611.tar.bz2 |
Make kadmin work over IPv6
Make gssrpc work over IPv6 TCP sockets provided that the client
creates and connects/binds the sockets and doesn't query their
addresses or use bindresvport(). Make kadmin work within those
constraints and handle IPv6. Specific changes:
* Make svctcp_create() able to extract the port from an IPv6 socket,
using a new helper function getport().
* Make clnttcp_create() handle a null raddr value if *sockp is set.
* Make kadm5_get_service_name() use getaddrinfo() to canonicalize the
admin server name.
* Make libkadm5clnt's init_any() responsible for connecting its socket
using a new helper function connect_to_server(), which uses
getaddrinfo instead of gethostbyname. Pass a null address to
clnttcp_create().
* Make libapputil's net-server.c set up IPv6 as well as IPv4 listener
ports for RPC connections.
* Adjust the error code expected in a libkadm5 unit test.
ticket: 6746
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@24147 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src/lib/kadm5')
-rw-r--r-- | src/lib/kadm5/alt_prof.c | 16 | ||||
-rw-r--r-- | src/lib/kadm5/clnt/client_init.c | 74 | ||||
-rw-r--r-- | src/lib/kadm5/unit-test/api.current/init-v2.exp | 2 |
3 files changed, 65 insertions, 27 deletions
diff --git a/src/lib/kadm5/alt_prof.c b/src/lib/kadm5/alt_prof.c index bc5eb23..6a79655 100644 --- a/src/lib/kadm5/alt_prof.c +++ b/src/lib/kadm5/alt_prof.c @@ -33,6 +33,7 @@ /* * alt_prof.c - Implement alternate profile file handling. */ +#include "fake-addrinfo.h" #include "k5-int.h" #include <kadm5/admin.h> #include "adm_proto.h" @@ -882,7 +883,8 @@ kadm5_get_admin_service_name(krb5_context ctx, { krb5_error_code ret; kadm5_config_params params_in, params_out; - struct hostent *hp; + struct addrinfo hint, *ai = NULL; + int err; memset(¶ms_in, 0, sizeof(params_in)); memset(¶ms_out, 0, sizeof(params_out)); @@ -898,8 +900,10 @@ kadm5_get_admin_service_name(krb5_context ctx, goto err_params; } - hp = gethostbyname(params_out.admin_server); - if (hp == NULL) { + memset(&hint, 0, sizeof(hint)); + hint.ai_flags = AI_CANONNAME; + err = getaddrinfo(params_out.admin_server, NULL, &hint, &ai); + if (err != 0) { ret = KADM5_CANT_RESOLVE; krb5_set_error_message(ctx, ret, "Cannot resolve address of admin server \"%s\" " @@ -907,13 +911,15 @@ kadm5_get_admin_service_name(krb5_context ctx, realm_in); goto err_params; } - if (strlen(hp->h_name) + sizeof("kadmin/") > maxlen) { + if (strlen(ai->ai_canonname) + sizeof("kadmin/") > maxlen) { ret = ENOMEM; goto err_params; } - snprintf(admin_name, maxlen, "kadmin/%s", hp->h_name); + snprintf(admin_name, maxlen, "kadmin/%s", ai->ai_canonname); err_params: + if (ai != NULL) + freeaddrinfo(ai); kadm5_free_config_params(ctx, ¶ms_out); return ret; } diff --git a/src/lib/kadm5/clnt/client_init.c b/src/lib/kadm5/clnt/client_init.c index 9301b4b..cc9664f 100644 --- a/src/lib/kadm5/clnt/client_init.c +++ b/src/lib/kadm5/clnt/client_init.c @@ -40,6 +40,7 @@ #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> +#include <fake-addrinfo.h> #include <k5-int.h> /* for KRB5_ADM_DEFAULT_PORT */ #include <krb5.h> #ifdef __STDC__ @@ -80,6 +81,9 @@ gic_iter(kadm5_server_handle_t handle, enum init_type init_type, unsigned int full_svcname_len); static kadm5_ret_t +connect_to_server(const char *hostname, int port, int *fd); + +static kadm5_ret_t setup_gss(kadm5_server_handle_t handle, kadm5_config_params *params_in, char *client_name, char *full_svcname); @@ -151,8 +155,6 @@ init_any(krb5_context context, char *client_name, enum init_type init_type, kadm5_config_params *params_in, krb5_ui_4 struct_version, krb5_ui_4 api_version, char **db_args, void **server_handle) { - struct sockaddr_in addr; - struct hostent *hp; int fd; krb5_boolean iprop_enable; @@ -271,20 +273,9 @@ init_any(krb5_context context, char *client_name, enum init_type init_type, sizeof(full_svcname)); if (code) goto error; - /* - * We have ticket; open the RPC connection. - */ - - hp = gethostbyname(handle->params.admin_server); - if (hp == (struct hostent *) NULL) { - code = KADM5_BAD_SERVER_NAME; - goto cleanup; - } - /* - * If the service_name and client_name are iprop-centric, - * we need to clnttcp_create to the appropriate RPC prog. - */ + /* If the service_name and client_name are iprop-centric, use the iprop + * port and RPC identifiers. */ iprop_enable = (service_name != NULL && strstr(service_name, KIPROP_SVC_NAME) != NULL && strstr(client_name, KIPROP_SVC_NAME) != NULL); @@ -298,13 +289,11 @@ init_any(krb5_context context, char *client_name, enum init_type init_type, rpc_vers = KADMVERS; } - memset(&addr, 0, sizeof(addr)); - addr.sin_family = hp->h_addrtype; - (void) memcpy(&addr.sin_addr, hp->h_addr, sizeof(addr.sin_addr)); - addr.sin_port = htons((u_short) port); + code = connect_to_server(handle->params.admin_server, port, &fd); + if (code) + goto error; - fd = RPC_ANYSOCK; - handle->clnt = clnttcp_create(&addr, rpc_prog, rpc_vers, &fd, 0, 0); + handle->clnt = clnttcp_create(NULL, rpc_prog, rpc_vers, &fd, 0, 0); if (handle->clnt == NULL) { code = KADM5_RPC_ERROR; #ifdef DEBUG @@ -562,6 +551,49 @@ error: return code; } +/* Set *fd to a socket connected to hostname and port. */ +static kadm5_ret_t +connect_to_server(const char *hostname, int port, int *fd) +{ + struct addrinfo hint, *addrs, *a; + char portbuf[32]; + int err, s; + kadm5_ret_t code; + + /* Look up the server's addresses. */ + (void) snprintf(portbuf, sizeof(portbuf), "%d", port); + memset(&hint, 0, sizeof(hint)); + hint.ai_socktype = SOCK_STREAM; +#ifdef AI_NUMERICSERV + hint.ai_flags = AI_NUMERICSERV; +#endif + err = getaddrinfo(hostname, portbuf, &hint, &addrs); + if (err != 0) + return KADM5_CANT_RESOLVE; + + /* Try to connect to each address until we succeed. */ + for (a = addrs; a != NULL; a = a->ai_next) { + s = socket(a->ai_family, a->ai_socktype, 0); + if (s == -1) { + code = KADM5_FAILURE; + goto cleanup; + } + err = connect(s, a->ai_addr, a->ai_addrlen); + if (err == 0) { + *fd = s; + code = 0; + goto cleanup; + } + close(s); + } + + /* We didn't succeed on any address. */ + code = KADM5_RPC_ERROR; +cleanup: + freeaddrinfo(addrs); + return code; +} + /* Acquire GSSAPI credentials and set up RPC auth flavor. */ static kadm5_ret_t setup_gss(kadm5_server_handle_t handle, kadm5_config_params *params_in, diff --git a/src/lib/kadm5/unit-test/api.current/init-v2.exp b/src/lib/kadm5/unit-test/api.current/init-v2.exp index a364b9c..7a353d4 100644 --- a/src/lib/kadm5/unit-test/api.current/init-v2.exp +++ b/src/lib/kadm5/unit-test/api.current/init-v2.exp @@ -70,7 +70,7 @@ proc test102 {} { [config_params {KADM5_CONFIG_ADMIN_SERVER} does.not.exist] \ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_3 \ server_handle - } "BAD_SERVER_NAME" + } "CANT_RESOLVE" } if {$RPC} test102 |