Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 46015977 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6: (21 commits)
  [CIFS] fix oops on second mount to same server when null auth is used
  [CIFS] Fix stale mode after readdir when cifsacl specified
  [CIFS] add mode to acl conversion helper function
  [CIFS] Fix incorrect mode when ACL had deny access control entries
  [CIFS] Add uid to key description so krb can handle user mounts
  [CIFS] Fix walking out end of cifs dacl
  [CIFS] Add upcall files for cifs to use spnego/kerberos
  [CIFS] add OIDs for KRB5 and MSKRB5 to ASN1 parsing routines
  [CIFS] Register and unregister cifs_spnego_key_type on module init/exit
  [CIFS] implement upcalls for SPNEGO blob via keyctl API
  [CIFS] allow cifs_calc_signature2 to deal with a zero length iovec
  [CIFS] If no Access Control Entries, set mode perm bits to zero
  [CIFS] when mount helper missing fix slash wrong direction in share
  [CIFS] Don't request too much permission when reading an ACL
  [CIFS] enable get mode from ACL when cifsacl mount option specified
  [CIFS] ACL support part 8
  [CIFS] acl support part 7
  [CIFS] acl support part 6
  [CIFS] acl support part 6
  [CIFS] remove unused funtion compile warning when experimental off
  ...
parents 92d140e2 9b8f5f57
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -2007,7 +2007,7 @@ config CIFS_EXPERIMENTAL
config CIFS_UPCALL
	  bool "Kerberos/SPNEGO advanced session setup (EXPERIMENTAL)"
	  depends on CIFS_EXPERIMENTAL
	  depends on CONNECTOR
	  depends on KEYS
	  help
	    Enables an upcall mechanism for CIFS which will be used to contact
	    userspace helper utilities to provide SPNEGO packaged Kerberos
+10 −1
Original line number Diff line number Diff line
Version 1.52
------------
Fix oops on second mount to server when null auth is used.

Version 1.51
------------
Fix memory leak in statfs when mounted to very old servers (e.g.
@@ -12,7 +16,12 @@ leak that causes cifsd not to stop and rmmod to fail to cleanup
cifs_request_buffers pool. Fix problem with POSIX Open/Mkdir on
bigendian architectures. Fix possible memory corruption when
EAGAIN returned on kern_recvmsg. Return better error if server
requires packet signing but client has disabled it.
requires packet signing but client has disabled it. When mounted
with cifsacl mount option - mode bits are approximated based
on the contents of the ACL of the file or directory. When cifs
mount helper is missing convert make sure that UNC name 
has backslash (not forward slash) between ip address of server
and the share name.

Version 1.50
------------
+6 −1
Original line number Diff line number Diff line
@@ -3,4 +3,9 @@
#
obj-$(CONFIG_CIFS) += cifs.o

cifs-objs := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o md4.o md5.o cifs_unicode.o nterr.o xattr.o cifsencrypt.o fcntl.o readdir.o ioctl.o sess.o export.o cifsacl.o
cifs-y := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o \
	  link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o \
	  md4.o md5.o cifs_unicode.o nterr.o xattr.o cifsencrypt.o fcntl.o \
	  readdir.o ioctl.o sess.o export.o cifsacl.o

cifs-$(CONFIG_CIFS_UPCALL) += cifs_spnego.o
+24 −11
Original line number Diff line number Diff line
@@ -77,8 +77,12 @@

#define SPNEGO_OID_LEN 7
#define NTLMSSP_OID_LEN  10
#define KRB5_OID_LEN  7
#define MSKRB5_OID_LEN  7
static unsigned long SPNEGO_OID[7] = { 1, 3, 6, 1, 5, 5, 2 };
static unsigned long NTLMSSP_OID[10] = { 1, 3, 6, 1, 4, 1, 311, 2, 2, 10 };
static unsigned long KRB5_OID[7] = { 1, 2, 840, 113554, 1, 2, 2 };
static unsigned long MSKRB5_OID[7] = { 1, 2, 840, 48018, 1, 2, 2 };

/*
 * ASN.1 context.
@@ -457,6 +461,7 @@ decode_negTokenInit(unsigned char *security_blob, int length,
	unsigned long *oid = NULL;
	unsigned int cls, con, tag, oidlen, rc;
	int use_ntlmssp = FALSE;
	int use_kerberos = FALSE;

	*secType = NTLM; /* BB eventually make Kerberos or NLTMSSP the default*/

@@ -545,18 +550,28 @@ decode_negTokenInit(unsigned char *security_blob, int length,
				return 0;
			}
			if ((tag == ASN1_OJI) && (con == ASN1_PRI)) {
				rc = asn1_oid_decode(&ctx, end, &oid, &oidlen);
				if (rc) {
				if (asn1_oid_decode(&ctx, end, &oid, &oidlen)) {

					cFYI(1,
					  ("OID len = %d oid = 0x%lx 0x%lx "
					   "0x%lx 0x%lx",
					   oidlen, *oid, *(oid + 1),
					   *(oid + 2), *(oid + 3)));
					rc = compare_oid(oid, oidlen,
						 NTLMSSP_OID, NTLMSSP_OID_LEN);
					kfree(oid);
					if (rc)

					if (compare_oid(oid, oidlen,
							MSKRB5_OID,
							MSKRB5_OID_LEN))
						use_kerberos = TRUE;
					else if (compare_oid(oid, oidlen,
							     KRB5_OID,
							     KRB5_OID_LEN))
						use_kerberos = TRUE;
					else if (compare_oid(oid, oidlen,
							     NTLMSSP_OID,
							     NTLMSSP_OID_LEN))
						use_ntlmssp = TRUE;

					kfree(oid);
				}
			} else {
				cFYI(1, ("Should be an oid what is going on?"));
@@ -609,12 +624,10 @@ decode_negTokenInit(unsigned char *security_blob, int length,
			 ctx.pointer));	/* is this UTF-8 or ASCII? */
	}

	/* if (use_kerberos)
	   *secType = Kerberos
	   else */
	if (use_ntlmssp) {
	if (use_kerberos)
		*secType = Kerberos;
	else if (use_ntlmssp)
		*secType = NTLMSSP;
	}

	return 1;
}

fs/cifs/cifs_spnego.c

0 → 100644
+128 −0
Original line number Diff line number Diff line
/*
 *   fs/cifs/cifs_spnego.c -- SPNEGO upcall management for CIFS
 *
 *   Copyright (c) 2007 Red Hat, Inc.
 *   Author(s): Jeff Layton (jlayton@redhat.com)
 *
 *   This library is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU Lesser General Public License as published
 *   by the Free Software Foundation; either version 2.1 of the License, or
 *   (at your option) any later version.
 *
 *   This library is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
 *   the GNU Lesser General Public License for more details.
 *
 *   You should have received a copy of the GNU Lesser General Public License
 *   along with this library; if not, write to the Free Software
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

#include <linux/list.h>
#include <linux/string.h>
#include <keys/user-type.h>
#include <linux/key-type.h>
#include "cifsglob.h"
#include "cifs_spnego.h"
#include "cifs_debug.h"

/* create a new cifs key */
static int
cifs_spnego_key_instantiate(struct key *key, const void *data, size_t datalen)
{
	char *payload;
	int ret;

	ret = -ENOMEM;
	payload = kmalloc(datalen, GFP_KERNEL);
	if (!payload)
		goto error;

	/* attach the data */
	memcpy(payload, data, datalen);
	rcu_assign_pointer(key->payload.data, payload);
	ret = 0;

error:
	return ret;
}

static void
cifs_spnego_key_destroy(struct key *key)
{
	kfree(key->payload.data);
}


/*
 * keytype for CIFS spnego keys
 */
struct key_type cifs_spnego_key_type = {
	.name		= "cifs.spnego",
	.instantiate	= cifs_spnego_key_instantiate,
	.match		= user_match,
	.destroy	= cifs_spnego_key_destroy,
	.describe	= user_describe,
};

/* get a key struct with a SPNEGO security blob, suitable for session setup */
struct key *
cifs_get_spnego_key(struct cifsSesInfo *sesInfo, const char *hostname)
{
	struct TCP_Server_Info *server = sesInfo->server;
	char *description, *dp;
	size_t desc_len;
	struct key *spnego_key;


	/* version + ;ip{4|6}= + address + ;host=hostname +
		;sec= + ;uid= + NULL */
	desc_len = 4 + 5 + 32 + 1 + 5 + strlen(hostname) +
		   strlen(";sec=krb5") + 7 + sizeof(uid_t)*2 + 1;
	spnego_key = ERR_PTR(-ENOMEM);
	description = kzalloc(desc_len, GFP_KERNEL);
	if (description == NULL)
		goto out;

	dp = description;
	/* start with version and hostname portion of UNC string */
	spnego_key = ERR_PTR(-EINVAL);
	sprintf(dp, "0x%2.2x;host=%s;", CIFS_SPNEGO_UPCALL_VERSION,
		hostname);
	dp = description + strlen(description);

	/* add the server address */
	if (server->addr.sockAddr.sin_family == AF_INET)
		sprintf(dp, "ip4=" NIPQUAD_FMT,
			NIPQUAD(server->addr.sockAddr.sin_addr));
	else if (server->addr.sockAddr.sin_family == AF_INET6)
		sprintf(dp, "ip6=" NIP6_SEQFMT,
			NIP6(server->addr.sockAddr6.sin6_addr));
	else
		goto out;

	dp = description + strlen(description);

	/* for now, only sec=krb5 is valid */
	if (server->secType == Kerberos)
		sprintf(dp, ";sec=krb5");
	else
		goto out;

	dp = description + strlen(description);
	sprintf(dp, ";uid=0x%x", sesInfo->linux_uid);

	cFYI(1, ("key description = %s", description));
	spnego_key = request_key(&cifs_spnego_key_type, description, "");

	if (cifsFYI && !IS_ERR(spnego_key)) {
		struct cifs_spnego_msg *msg = spnego_key->payload.data;
		cifs_dump_mem("SPNEGO reply blob:", msg->data,
				msg->secblob_len + msg->sesskey_len);
	}

out:
	kfree(description);
	return spnego_key;
}
Loading