From patchwork Wed Aug 19 17:30:37 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff Layton X-Patchwork-Id: 31663 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.samba.org (fn.samba.org [216.83.154.106]) by bilbo.ozlabs.org (Postfix) with ESMTP id EBBAAB70BA for ; Thu, 20 Aug 2009 03:31:17 +1000 (EST) Received: from fn.samba.org (localhost [127.0.0.1]) by lists.samba.org (Postfix) with ESMTP id 1C826AD01C; Wed, 19 Aug 2009 11:24:31 -0600 (MDT) X-Spam-Checker-Version: SpamAssassin 3.2.5 (2008-06-10) on fn.samba.org X-Spam-Level: X-Spam-Status: No, score=-5.9 required=3.8 tests=AWL,BAYES_00, RCVD_IN_DNSWL_MED, RDNS_NONE, SPF_HELO_PASS, SPF_PASS autolearn=unavailable version=3.2.5 X-Original-To: linux-cifs-client@lists.samba.org Delivered-To: linux-cifs-client@lists.samba.org Received: from mx2.redhat.com (unknown [66.187.237.31]) by lists.samba.org (Postfix) with ESMTP id A408FACF6C; Wed, 19 Aug 2009 11:24:23 -0600 (MDT) Received: from int-mx2.corp.redhat.com (int-mx2.corp.redhat.com [172.16.27.26]) by mx2.redhat.com (8.13.8/8.13.8) with ESMTP id n7JHUcdJ021418; Wed, 19 Aug 2009 13:30:38 -0400 Received: from ns3.rdu.redhat.com (ns3.rdu.redhat.com [10.11.255.199]) by int-mx2.corp.redhat.com (8.13.1/8.13.1) with ESMTP id n7JHUbu7002535; Wed, 19 Aug 2009 13:30:38 -0400 Received: from localhost.localdomain (vpn-8-24.rdu.redhat.com [10.11.8.24]) by ns3.rdu.redhat.com (8.13.8/8.13.8) with ESMTP id n7JHUbXZ027334; Wed, 19 Aug 2009 13:30:37 -0400 From: Jeff Layton To: niallain@gmail.com Date: Wed, 19 Aug 2009 13:30:37 -0400 Message-Id: <1250703037-3640-1-git-send-email-jlayton@redhat.com> X-Scanned-By: MIMEDefang 2.58 on 172.16.27.26 Cc: samba-technical@lists.samba.org, linux-cifs-client@lists.samba.org Subject: [linux-cifs-client] [PATCH] cifs.upcall: make using ip address conditional on new option X-BeenThere: linux-cifs-client@lists.samba.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: The Linux CIFS VFS client List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: linux-cifs-client-bounces@lists.samba.org Errors-To: linux-cifs-client-bounces@lists.samba.org Igor Mammedov pointed out that reverse resolving an IP address to get the hostname portion of a principal could open a possible attack vector. If an attacker were to gain control of DNS, then he could redirect the mount to a server of his choosing, and fix the reverse resolution to point to a hostname of his choosing (one where he has the key for the corresponding cifs/ or host/ principal). That said, we often trust DNS for other reasons and it can be useful to do so. Make the code that allows trusting DNS to be enabled by adding --trust-dns to the cifs.upcall invocation. Signed-off-by: Jeff Layton --- client/cifs.upcall.c | 62 ++++++++++++++++++++++++++++++++----------------- 1 files changed, 40 insertions(+), 22 deletions(-) diff --git a/client/cifs.upcall.c b/client/cifs.upcall.c index f06d563..1645322 100644 --- a/client/cifs.upcall.c +++ b/client/cifs.upcall.c @@ -154,9 +154,9 @@ handle_krb5_mech(const char *oid, const char *principal, DATA_BLOB *secblob, #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) +#define DKD_MUSTHAVE_SET (DKD_HAVE_HOSTNAME|DKD_HAVE_VERSION|DKD_HAVE_SEC) -static struct decoded_args { +struct decoded_args { int ver; char *hostname; char *ip; @@ -354,11 +354,12 @@ ip_to_fqdn(const char *addrstr, char *host, size_t hostlen) static void usage(void) { - syslog(LOG_INFO, "Usage: %s [-v] key_serial", prog); - fprintf(stderr, "Usage: %s [-v] key_serial\n", prog); + syslog(LOG_INFO, "Usage: %s [-t] [-v] key_serial", prog); + fprintf(stderr, "Usage: %s [-t] [-v] key_serial\n", prog); } const struct option long_options[] = { + { "trust-dns", 0, NULL, 't' }, { "version", 0, NULL, 'v' }, { NULL, 0, NULL, 0 } }; @@ -372,19 +373,24 @@ int main(const int argc, char *const argv[]) size_t datalen; unsigned int have; long rc = 1; - int c; - char *buf, *princ, *ccname = NULL; - char hostbuf[NI_MAXHOST]; + int c, try_dns = 0; + char *buf, *princ = NULL, *ccname = NULL; + char hostbuf[NI_MAXHOST], *host; struct decoded_args arg = { }; const char *oid; + hostbuf[0] = '\0'; + openlog(prog, 0, LOG_DAEMON); - while ((c = getopt_long(argc, argv, "cv", long_options, NULL)) != -1) { + while ((c = getopt_long(argc, argv, "ctv", long_options, NULL)) != -1) { switch (c) { case 'c': /* legacy option -- skip it */ break; + case 't': + try_dns++; + break; case 'v': printf("version: %s\n", CIFSSPNEGO_VERSION); goto out; @@ -452,21 +458,18 @@ int main(const int argc, char *const argv[]) if (have & DKD_HAVE_PID) ccname = get_krb5_ccname(arg.pid); - if (have & DKD_HAVE_IP) { - rc = ip_to_fqdn(arg.ip, hostbuf, sizeof(hostbuf)); - if (rc) - goto out; - } + host = arg.hostname; // do mech specific authorization switch (arg.sec) { case MS_KRB5: case KRB5: +retry_new_hostname: /* for "cifs/" service name + terminating 0 */ - datalen = strnlen(hostbuf, sizeof(hostbuf)) + 5 + 1; + datalen = strlen(host) + 5 + 1; princ = SMB_XMALLOC_ARRAY(char, datalen); if (!princ) { - rc = 1; + rc = -ENOMEM; break; } @@ -480,21 +483,35 @@ int main(const int argc, char *const argv[]) * getting a host/ principal if that doesn't work. */ strlcpy(princ, "cifs/", datalen); - strlcpy(princ + 5, hostbuf, datalen - 5); + strlcpy(princ + 5, host, datalen - 5); rc = handle_krb5_mech(oid, princ, &secblob, &sess_key, ccname); - if (rc) { - memcpy(princ, "host/", 5); - rc = handle_krb5_mech(oid, princ, &secblob, &sess_key, - ccname); - } + if (!rc) + break; + + memcpy(princ, "host/", 5); + rc = handle_krb5_mech(oid, princ, &secblob, &sess_key, ccname); + if (!rc) + break; + + if (!try_dns || !(have & DKD_HAVE_IP)) + break; + + rc = ip_to_fqdn(arg.ip, hostbuf, sizeof(hostbuf)); + if (rc) + break; + SAFE_FREE(princ); - break; + try_dns = 0; + host = hostbuf; + goto retry_new_hostname; default: syslog(LOG_ERR, "sectype: %d is not implemented", arg.sec); rc = 1; break; } + SAFE_FREE(princ); + if (rc) goto out; @@ -536,6 +553,7 @@ out: data_blob_free(&sess_key); SAFE_FREE(ccname); SAFE_FREE(arg.hostname); + SAFE_FREE(arg.ip); SAFE_FREE(keydata); return rc; }