[PATCH 6/7] cifs.upcall: use ip address passed by kernel to get server's hostname

Jeff Layton jlayton at redhat.com
Fri Aug 7 13:43:16 MDT 2009


Instead of using the hostname given by the upcall to get the server's
principal, take the IP address given in the upcall and reverse resolve
it to a hostname.

Signed-off-by: Jeff Layton <jlayton at redhat.com>
---
 client/cifs.upcall.c |   68 +++++++++++++++++++++++++++++++++++++++++---------
 1 files changed, 56 insertions(+), 12 deletions(-)

diff --git a/client/cifs.upcall.c b/client/cifs.upcall.c
index 38be876..1e58503 100644
--- a/client/cifs.upcall.c
+++ b/client/cifs.upcall.c
@@ -150,15 +150,15 @@ handle_krb5_mech(const char *oid, const char *principal, DATA_BLOB *secblob,
 #define DKD_HAVE_HOSTNAME	0x1
 #define DKD_HAVE_VERSION	0x2
 #define DKD_HAVE_SEC		0x4
-#define DKD_HAVE_IPV4		0x8
-#define DKD_HAVE_IPV6		0x10
-#define DKD_HAVE_UID		0x20
-#define DKD_HAVE_PID		0x40
-#define DKD_MUSTHAVE_SET (DKD_HAVE_HOSTNAME|DKD_HAVE_VERSION|DKD_HAVE_SEC)
+#define DKD_HAVE_IP		0x8
+#define DKD_HAVE_UID		0x10
+#define DKD_HAVE_PID		0x20
+#define DKD_MUSTHAVE_SET (DKD_HAVE_IP|DKD_HAVE_VERSION|DKD_HAVE_SEC)
 
 static struct decoded_args {
 	int		ver;
 	char		*hostname;
+	char		*ip;
 	uid_t		uid;
 	pid_t		pid;
 	sectype_t	sec;
@@ -167,6 +167,7 @@ static struct decoded_args {
 static unsigned int
 decode_key_description(const char *desc, struct decoded_args *arg)
 {
+	int len;
 	int retval = 0;
 	char *pos;
 	const char *tkn = desc;
@@ -174,7 +175,6 @@ decode_key_description(const char *desc, struct decoded_args *arg)
 	do {
 		pos = index(tkn, ';');
 		if (strncmp(tkn, "host=", 5) == 0) {
-			int len;
 
 			if (pos == NULL)
 				len = strlen(tkn);
@@ -186,10 +186,18 @@ decode_key_description(const char *desc, struct decoded_args *arg)
 			arg->hostname = SMB_XMALLOC_ARRAY(char, len);
 			strlcpy(arg->hostname, tkn + 5, len);
 			retval |= DKD_HAVE_HOSTNAME;
-		} else if (strncmp(tkn, "ipv4=", 5) == 0) {
-			/* BB: do we need it if we have hostname already? */
-		} else if (strncmp(tkn, "ipv6=", 5) == 0) {
-			/* BB: do we need it if we have hostname already? */
+		} else if (!strncmp(tkn, "ip4=", 4) ||
+			   !strncmp(tkn, "ip6=", 4)) {
+			if (pos == NULL)
+				len = strlen(tkn);
+			else
+				len = pos - tkn;
+
+			len -= 3;
+			SAFE_FREE(arg->ip);
+			arg->ip = SMB_XMALLOC_ARRAY(char, len);
+			strlcpy(arg->ip, tkn + 4, len);
+			retval |= DKD_HAVE_IP;
 		} else if (strncmp(tkn, "pid=", 4) == 0) {
 			errno = 0;
 			arg->pid = strtol(tkn + 4, NULL, 0);
@@ -288,6 +296,35 @@ cifs_resolver(const key_serial_t key, const char *key_descr)
 	return 0;
 }
 
+static int
+ip_to_fqdn(const char *ipaddr, char *host, size_t hostlen)
+{
+	int rc;
+	struct addrinfo hints = { .ai_flags = AI_NUMERICHOST };
+	struct addrinfo *res;
+
+	rc = getaddrinfo(ipaddr, NULL, &hints, &res);
+	if (rc) {
+		syslog(LOG_DEBUG, "%s: failed to resolve %s to ipaddr: %s",
+			__func__, ipaddr,
+			rc == EAI_SYSTEM ? strerror(errno) : gai_strerror(rc));
+		return rc;
+	}
+
+	rc = getnameinfo(res->ai_addr, res->ai_addrlen, host, hostlen,
+			 NULL, 0, NI_NAMEREQD);
+	freeaddrinfo(res);
+	if (rc) {
+		syslog(LOG_DEBUG, "%s: failed to resolve %s to fqdn: %s",
+			__func__, ipaddr,
+			rc == EAI_SYSTEM ? strerror(errno) : gai_strerror(rc));
+		return rc;
+	}
+
+	syslog(LOG_DEBUG, "%s: resolved %s to %s", __func__, ipaddr, host);
+	return 0;
+}
+
 static void
 usage(void)
 {
@@ -306,6 +343,7 @@ int main(const int argc, char *const argv[])
 	long rc = 1;
 	int c;
 	char *buf, *princ, *ccname = NULL;
+	char hostbuf[NI_MAXHOST];
 	struct decoded_args arg = { };
 	const char *oid;
 
@@ -383,12 +421,18 @@ int main(const int argc, char *const argv[])
 		}
 	}
 
+	if (have & DKD_HAVE_IP) {
+		rc = ip_to_fqdn(arg.ip, hostbuf, sizeof(hostbuf));
+		if (rc)
+			goto out;
+	}
+
 	// do mech specific authorization
 	switch (arg.sec) {
 	case MS_KRB5:
 	case KRB5:
 		/* for "cifs/" service name + terminating 0 */
-		datalen = strlen(arg.hostname) + 5 + 1;
+		datalen = strnlen(hostbuf, sizeof(hostbuf)) + 5 + 1;
 		princ = SMB_XMALLOC_ARRAY(char, datalen);
 		if (!princ) {
 			rc = 1;
@@ -405,7 +449,7 @@ int main(const int argc, char *const argv[])
 		 * getting a host/ principal if that doesn't work.
 		 */
 		strlcpy(princ, "cifs/", datalen);
-		strlcpy(princ + 5, arg.hostname, datalen - 5);
+		strlcpy(princ + 5, hostbuf, datalen - 5);
 		rc = handle_krb5_mech(oid, princ, &secblob, &sess_key, ccname);
 		if (rc) {
 			memcpy(princ, "host/", 5);
-- 
1.6.0.6



More information about the samba-technical mailing list