#include <errno.h>
#include <gssapi/gssapi.h>
#include <netdb.h>
+#include <ctype.h>
#include "gssd.h"
#include "err_util.h"
unsigned long pollsize; /* the size of pollaray (in pollfd's) */
+/* Avoid DNS reverse lookups on server names */
+int avoid_dns = 1;
+
/*
* convert a presentation address string to a sockaddr_storage struct. Returns
* true on success or false on failure.
* convert a sockaddr to a hostname
*/
static char *
-sockaddr_to_hostname(const struct sockaddr *sa, const char *addr)
+get_servername(const char *name, const struct sockaddr *sa, const char *addr)
{
socklen_t addrlen;
int err;
char *hostname;
char hbuf[NI_MAXHOST];
+ unsigned char buf[sizeof(struct in6_addr)];
+ int servername = 0;
+
+ if (avoid_dns) {
+ /*
+ * Determine if this is a server name, or an IP address.
+ * If it is an IP address, do the DNS lookup otherwise
+ * skip the DNS lookup.
+ */
+ servername = 0;
+ if (strchr(name, '.') && inet_pton(AF_INET, name, buf) == 1)
+ servername = 1; /* IPv4 */
+ else if (strchr(name, ':') && inet_pton(AF_INET6, name, buf) == 1)
+ servername = 1; /* or IPv6 */
+
+ if (servername) {
+ return strdup(name);
+ }
+ }
switch (sa->sa_family) {
case AF_INET:
struct sockaddr *addr) {
#define INFOBUFLEN 256
char buf[INFOBUFLEN + 1];
- static char dummy[128];
+ static char server[128];
int nbytes;
static char service[128];
static char address[128];
"service: %127s %15s version %15s\n"
"address: %127s\n"
"protocol: %15s\n",
- dummy,
+ server,
service, program, version,
address,
protoname);
if (!addrstr_to_sockaddr(addr, address, port))
goto fail;
- *servername = sockaddr_to_hostname(addr, address);
+ *servername = get_servername(server, addr, address);
if (*servername == NULL)
goto fail;
CLIENT **clnt_return,
AUTH **auth_return,
uid_t uid,
- int authtype)
+ int authtype,
+ gss_cred_id_t cred)
{
CLIENT *rpc_clnt = NULL;
struct rpc_gss_sec sec;
sec.qop = GSS_C_QOP_DEFAULT;
sec.svc = RPCSEC_GSS_SVC_NONE;
- sec.cred = GSS_C_NO_CREDENTIAL;
+ sec.cred = cred;
sec.req_flags = 0;
if (authtype == AUTHTYPE_KRB5) {
sec.mech = (gss_OID)&krb5oid;
char **dirname;
int create_resp = -1;
int err, downcall_err = -EACCES;
+ gss_cred_id_t gss_cred;
OM_uint32 maj_stat, min_stat, lifetime_rec;
printerr(1, "handling krb5 upcall (%s)\n", clp->dirname);
if (uid != 0 || (uid == 0 && root_uses_machine_creds == 0 &&
service == NULL)) {
/* Tell krb5 gss which credentials cache to use */
- for (dirname = ccachesearch; *dirname != NULL; dirname++) {
+ /* Try first to acquire credentials directly via GSSAPI */
+ err = gssd_acquire_user_cred(uid, &gss_cred);
+ if (!err)
+ create_resp = create_auth_rpc_client(clp, &rpc_clnt, &auth, uid,
+ AUTHTYPE_KRB5, gss_cred);
+ /* if create_auth_rplc_client fails try the traditional method of
+ * trolling for credentials */
+ for (dirname = ccachesearch; create_resp != 0 && *dirname != NULL; dirname++) {
err = gssd_setup_krb5_user_gss_ccache(uid, clp->servername, *dirname);
if (err == -EKEYEXPIRED)
downcall_err = -EKEYEXPIRED;
else if (!err)
create_resp = create_auth_rpc_client(clp, &rpc_clnt, &auth, uid,
- AUTHTYPE_KRB5);
- if (create_resp == 0)
- break;
+ AUTHTYPE_KRB5, GSS_C_NO_CREDENTIAL);
}
}
if (create_resp != 0) {
gssd_setup_krb5_machine_gss_ccache(*ccname);
if ((create_auth_rpc_client(clp, &rpc_clnt,
&auth, uid,
- AUTHTYPE_KRB5)) == 0) {
+ AUTHTYPE_KRB5,
+ GSS_C_NO_CREDENTIAL)) == 0) {
/* Success! */
success++;
break;