*/
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif /* HAVE_CONFIG_H */
+
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
-#include "config.h"
+
#include <sys/param.h>
#include <rpc/rpc.h>
#include <sys/stat.h>
#include "gssd.h"
#include "err_util.h"
#include "gss_util.h"
-#include "gss_oids.h"
#include "krb5_util.h"
#include "context.h"
int pollsize; /* the size of pollaray (in pollfd's) */
+/*
+ * convert a presentation address string to a sockaddr_storage struct. Returns
+ * true on success and false on failure.
+ */
+static int
+addrstr_to_sockaddr(struct sockaddr *sa, const char *addr, const int port)
+{
+ struct sockaddr_in *s4 = (struct sockaddr_in *) sa;
+
+ if (inet_pton(AF_INET, addr, &s4->sin_addr)) {
+ s4->sin_family = AF_INET;
+ s4->sin_port = htons(port);
+ } else {
+ printerr(0, "ERROR: unable to convert %s to address\n", addr);
+ return 0;
+ }
+
+ return 1;
+}
+
+/*
+ * convert a sockaddr to a hostname
+ */
+static char *
+sockaddr_to_hostname(const struct sockaddr *sa, const char *addr)
+{
+ socklen_t addrlen;
+ int err;
+ char *hostname;
+ char hbuf[NI_MAXHOST];
+
+ switch (sa->sa_family) {
+ case AF_INET:
+ addrlen = sizeof(struct sockaddr_in);
+ break;
+ default:
+ printerr(0, "ERROR: unrecognized addr family %d\n",
+ sa->sa_family);
+ return NULL;
+ }
+
+ err = getnameinfo(sa, addrlen, hbuf, sizeof(hbuf), NULL, 0,
+ NI_NAMEREQD);
+ if (err) {
+ printerr(0, "ERROR: unable to resolve %s to hostname: %s\n",
+ addr, err == EAI_SYSTEM ? strerror(err) :
+ gai_strerror(err));
+ return NULL;
+ }
+
+ hostname = strdup(hbuf);
+
+ return hostname;
+}
+
/* XXX buffer problems: */
static int
read_service_info(char *info_file_name, char **servicename, char **servername,
- int *prog, int *vers, char **protocol, int *port) {
+ int *prog, int *vers, char **protocol,
+ struct sockaddr *addr) {
#define INFOBUFLEN 256
- char buf[INFOBUFLEN];
+ char buf[INFOBUFLEN + 1];
static char dummy[128];
int nbytes;
static char service[128];
char protoname[16];
char cb_port[128];
char *p;
- in_addr_t inaddr;
int fd = -1;
- struct hostent *ent = NULL;
int numfields;
+ int port = 0;
*servicename = *servername = *protocol = NULL;
if ((nbytes = read(fd, buf, INFOBUFLEN)) == -1)
goto fail;
close(fd);
+ buf[nbytes] = '\0';
numfields = sscanf(buf,"RPC server: %127s\n"
"service: %127s %15s version %15s\n"
if((*prog != 100003) || ((*vers != 2) && (*vers != 3) && (*vers != 4)))
goto fail;
- /* create service name */
- inaddr = inet_addr(address);
- if (!(ent = gethostbyaddr(&inaddr, sizeof(inaddr), AF_INET))) {
- printerr(0, "ERROR: can't resolve server %s name\n", address);
- goto fail;
+ if (cb_port[0] != '\0') {
+ port = atoi(cb_port);
+ if (port < 0 || port > 65535)
+ goto fail;
}
- if (!(*servername = calloc(strlen(ent->h_name) + 1, 1)))
+
+ if (!addrstr_to_sockaddr(addr, address, port))
+ goto fail;
+
+ *servername = sockaddr_to_hostname(addr, address);
+ if (*servername == NULL)
goto fail;
- memcpy(*servername, ent->h_name, strlen(ent->h_name));
- snprintf(buf, INFOBUFLEN, "%s@%s", service, ent->h_name);
+
+ nbytes = snprintf(buf, INFOBUFLEN, "%s@%s", service, *servername);
+ if (nbytes > INFOBUFLEN)
+ goto fail;
+
if (!(*servicename = calloc(strlen(buf) + 1, 1)))
goto fail;
memcpy(*servicename, buf, strlen(buf));
- if (cb_port[0] != '\0')
- *port = atoi(cb_port);
if (!(*protocol = strdup(protoname)))
goto fail;
fail:
printerr(0, "ERROR: failed to read service info\n");
if (fd != -1) close(fd);
- if (*servername) free(*servername);
- if (*servicename) free(*servicename);
- if (*protocol) free(*protocol);
+ free(*servername);
+ free(*servicename);
+ free(*protocol);
+ *servicename = *servername = *protocol = NULL;
return -1;
}
if (clp->dir_fd != -1) close(clp->dir_fd);
if (clp->krb5_fd != -1) close(clp->krb5_fd);
if (clp->spkm3_fd != -1) close(clp->spkm3_fd);
- if (clp->dirname) free(clp->dirname);
- if (clp->servicename) free(clp->servicename);
- if (clp->servername) free(clp->servername);
- if (clp->protocol) free(clp->protocol);
+ free(clp->dirname);
+ free(clp->servicename);
+ free(clp->servername);
+ free(clp->protocol);
free(clp);
}
if ((clp->servicename == NULL) &&
read_service_info(info_file_name, &clp->servicename,
&clp->servername, &clp->prog, &clp->vers,
- &clp->protocol, &clp->port))
+ &clp->protocol, (struct sockaddr *) &clp->addr))
return -1;
return 0;
}
gss_buffer_desc *context_token)
{
char *buf = NULL, *p = NULL, *end = NULL;
- unsigned int timeout = 0; /* XXX decide on a reasonable value */
+ unsigned int timeout = context_timeout;
unsigned int buf_size = 0;
printerr(1, "doing downcall\n");
end = buf + buf_size;
if (WRITE_BYTES(&p, end, uid)) goto out_err;
- /* Not setting any timeout for now: */
if (WRITE_BYTES(&p, end, timeout)) goto out_err;
if (WRITE_BYTES(&p, end, pd->pd_seq_win)) goto out_err;
if (write_buffer(&p, end, &pd->pd_ctx_hndl)) goto out_err;
return 0;
out_err:
if (buf) free(buf);
- printerr(0, "Failed to write downcall!\n");
+ printerr(1, "Failed to write downcall!\n");
return -1;
}
struct addrinfo ai_hints, *a = NULL;
char service[64];
char *at_sign;
+ struct sockaddr_in *addr = (struct sockaddr_in *) &clp->addr;
/* Create the context as the user (not as root) */
save_uid = geteuid();
clp->servername, uid);
goto out_fail;
}
- if (clp->port)
- ((struct sockaddr_in *)a->ai_addr)->sin_port = htons(clp->port);
+
+ if (addr->sin_port != 0)
+ ((struct sockaddr_in *) a->ai_addr)->sin_port = addr->sin_port;
+
if (a->ai_protocol == IPPROTO_TCP) {
if ((rpc_clnt = clnttcp_create(
(struct sockaddr_in *) a->ai_addr,
}
gssd_free_krb5_machine_cred_list(credlist);
if (!success) {
- printerr(0, "WARNING: Failed to create krb5 context "
+ printerr(1, "WARNING: Failed to create krb5 context "
"for user with uid %d with any "
"credentials cache for server %s\n",
uid, clp->servername);
goto out_return_error;
}
} else {
- printerr(0, "WARNING: Failed to create krb5 context "
+ printerr(1, "WARNING: Failed to create krb5 context "
"for user with uid %d for server %s\n",
uid, clp->servername);
goto out_return_error;
}
if (!authgss_get_private_data(auth, &pd)) {
- printerr(0, "WARNING: Failed to obtain authentication "
+ printerr(1, "WARNING: Failed to obtain authentication "
"data for user with uid %d for server %s\n",
uid, clp->servername);
goto out_return_error;
}
- if (serialize_context_for_kernel(pd.pd_ctx, &token, &krb5oid)) {
+ if (serialize_context_for_kernel(pd.pd_ctx, &token, &krb5oid, NULL)) {
printerr(0, "WARNING: Failed to serialize krb5 context for "
"user with uid %d for server %s\n",
uid, clp->servername);
out:
if (token.value)
free(token.value);
+#ifndef HAVE_LIBTIRPC
if (pd.pd_ctx_hndl.length != 0)
authgss_free_private_data(&pd);
+#endif
if (auth)
AUTH_DESTROY(auth);
if (rpc_clnt)
goto out_return_error;
}
- if (serialize_context_for_kernel(pd.pd_ctx, &token, &spkm3oid)) {
+ if (serialize_context_for_kernel(pd.pd_ctx, &token, &spkm3oid, NULL)) {
printerr(0, "WARNING: Failed to serialize spkm3 context for "
"user with uid %d for server\n",
uid, clp->servername);