From patchwork Tue Apr 19 13:21:38 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Shirish Pargaonkar X-Patchwork-Id: 718001 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id p3JDILFI022386 for ; Tue, 19 Apr 2011 13:18:21 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755026Ab1DSNSU (ORCPT ); Tue, 19 Apr 2011 09:18:20 -0400 Received: from mail-yx0-f174.google.com ([209.85.213.174]:58369 "EHLO mail-yx0-f174.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754476Ab1DSNSU (ORCPT ); Tue, 19 Apr 2011 09:18:20 -0400 Received: by yxs7 with SMTP id 7so1968497yxs.19 for ; Tue, 19 Apr 2011 06:18:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:from:to:cc:subject:date:message-id:x-mailer; bh=UdN7AqlleCSu8ohC7HPvIb+0tOohGRAcn4YDBYpxJHE=; b=Ksv5o6uEu0OOktpruUiukb0ium922MCwdZoaX653EfDdGmpIa+s5FNHlpaaCsyNsy8 qJJgmBNyBn+NtqImF5ucQEnlAVetZn4VvmHBSTGx99cZ5qdQDcDbfkQEq3Bt9FK2EkJl oxtCelj1+IY2ZJafXIiY3iMcYi1vy3Kr4WaQM= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=from:to:cc:subject:date:message-id:x-mailer; b=GC+sOPPGFiiBuaH8+tCsJhXlczsTxgFj/5jd07TIWlDIoi1PwGbd1K9Pej4ahoO5GL mAe/TniJXwwwGXE3piFPAfvfdOcdcvmAHkp/28fNDTYYXRMS5GaiqC5Db4UzaAuFW7HR 7Ur00rbFFe1Qn0MxnT5Xls6XCQgbcZc29bbE8= Received: by 10.101.73.2 with SMTP id a2mr3276854anl.71.1303219099693; Tue, 19 Apr 2011 06:18:19 -0700 (PDT) Received: from localhost ([32.97.110.58]) by mx.google.com with ESMTPS id c38sm6410900anc.44.2011.04.19.06.18.18 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 19 Apr 2011 06:18:19 -0700 (PDT) From: shirishpargaonkar@gmail.com To: jlayton@redhat.com Cc: linux-cifs@vger.kernel.org, Shirish Pargaonkar Subject: [PATCH] cifs-utils: Handle cifs_idmap type of key to map a SID to either an uid or gid (try #16) Date: Tue, 19 Apr 2011 08:21:38 -0500 Message-Id: <1303219298-31170-1-git-send-email-shirishpargaonkar@gmail.com> X-Mailer: git-send-email 1.6.0.2 Sender: linux-cifs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-cifs@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter1.kernel.org [140.211.167.41]); Tue, 19 Apr 2011 13:18:22 +0000 (UTC) From: Shirish Pargaonkar Handle cifs_idmap type of key. Extract a SID string from the description and map it to either an uid or gid using winbind APIs. If that fails (e.g. because winbind is not installed/running or winbind returns an error), try to obtain uid of 'nobody' and gid of 'nogroup'. And if that fails, kernel assigns uid and gid (from mount superblock). An entry such as this create cifs.cifs_idmap * * /usr/sbin/cifs.upcall %k is needed in the file /etc/request-key.conf. Signed-off-by: Shirish Pargaonkar --- Makefile.am | 2 +- cifs.upcall.c | 110 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 111 insertions(+), 1 deletions(-) diff --git a/Makefile.am b/Makefile.am index 67a0190..c9018ae 100644 --- a/Makefile.am +++ b/Makefile.am @@ -11,7 +11,7 @@ man_MANS = mount.cifs.8 if CONFIG_CIFSUPCALL sbin_PROGRAMS = cifs.upcall cifs_upcall_SOURCES = cifs.upcall.c data_blob.c asn1.c spnego.c util.c -cifs_upcall_LDADD = -ltalloc -lkeyutils $(KRB5_LDADD) +cifs_upcall_LDADD = -ltalloc -lwbclient -lkeyutils $(KRB5_LDADD) man_MANS += cifs.upcall.8 # diff --git a/cifs.upcall.c b/cifs.upcall.c index 479517c..68a8059 100644 --- a/cifs.upcall.c +++ b/cifs.upcall.c @@ -45,6 +45,13 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include #include "util.h" #include "replace.h" @@ -695,6 +702,103 @@ static int cifs_resolver(const key_serial_t key, const char *key_descr) return 0; } +static int +cifs_sid_resolver(const key_serial_t key, const char *key_descr) +{ + int i; + uid_t uid = 0; + gid_t gid = 0;; + wbcErr rc = 1; + const char *keyend = key_descr; + struct wbcDomainSid sid; + struct passwd *pw; + struct group *gr; + + /* skip next 4 ';' delimiters to get to description */ + for (i = 1; i <= 4; ++i) { + keyend = index(keyend + 1, ';'); + if (!keyend) { + syslog(LOG_ERR, "invalid key description: %s", + key_descr); + return 1; + } + } + keyend++; + + /* + * Use winbind to convert received string to a SID and lookup + * name and map that SID to an uid. If either of these + * function calls return with an error, use system calls to obtain + * uid of user "nobody". If winbind fails to map a SID to an UID + * and there is no user named "nobody", return error to the + * upcall caller. Otherwise instanticate a key using that uid. + * + * The same applies to SID and gid mapping. Instead of a + * user "nobody", user "nogroup" is looked up if winbind + * fails to map a SID to a gid. + */ + if (strncmp(keyend, "os", 2) == 0) { + keyend = index(keyend + 1, ':'); + keyend++; + rc = wbcStringToSid(keyend, &sid); + if (rc) + syslog(LOG_DEBUG, "O strtosid: %s, rc: %d", keyend, rc); + else { + rc = wbcSidToUid(&sid, &uid); + if (rc) + syslog(LOG_DEBUG, "SID %s to uid wbc error: %d", + keyend, rc); + } + if (rc) { /* either of the two wbcSid functions failed */ + pw = getpwnam("nobody"); + if (!pw) + syslog(LOG_DEBUG, "SID %s to uid pw error: %d", + keyend, rc); + else { + uid = pw->pw_uid; + rc = 0; + } + } + if (!rc) { /* SID has been mapped to a uid */ + rc = keyctl_instantiate(key, &uid, sizeof(uid_t), 0); + if (rc) + syslog(LOG_ERR, "%s: key inst: %s", + __func__, strerror(errno)); + } + } else if (strncmp(keyend, "gs", 2) == 0) { + keyend = index(keyend + 1, ':'); + keyend++; + rc = wbcStringToSid(keyend, &sid); + if (rc) + syslog(LOG_DEBUG, "O strtosid: %s, rc: %d", keyend, rc); + else { + rc = wbcSidToGid(&sid, &gid); + if (rc) + syslog(LOG_DEBUG, "SID %s to gid wbc error: %d", + keyend, rc); + } + if (rc) { /* either of the two wbcSid functions failed */ + gr = getgrnam("nogroup"); + if (!gr) + syslog(LOG_DEBUG, "SID %s to gid pw error: %d", + keyend, rc); + else { + gid = gr->gr_gid; + rc = 0; + } + } + if (!rc) { /* SID has been mapped to a gid */ + rc = keyctl_instantiate(key, &gid, sizeof(gid_t), 0); + if (rc) + syslog(LOG_ERR, "%s: key inst: %s", + __func__, strerror(errno)); + } + } else + syslog(LOG_DEBUG, "Invalid SID: %s", keyend); + + return rc; +} + /* * Older kernels sent IPv6 addresses without colons. Well, at least * they're fixed-length strings. Convert these addresses to have colon @@ -833,6 +937,12 @@ int main(const int argc, char *const argv[]) goto out; } + if ((strncmp(buf, "cifs.cifs_idmap", sizeof("cifs.cifs_idmap") - 1) + == 0)) { + rc = cifs_sid_resolver(key, buf); + goto out; + } + have = decode_key_description(buf, &arg); SAFE_FREE(buf); if ((have & DKD_MUSTHAVE_SET) != DKD_MUSTHAVE_SET) {