Skip to content

Commit

Permalink
Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6
Browse files Browse the repository at this point in the history
* git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6:
  [DNS RESOLVER] Minor typo correction
  DNS: Fixes for the DNS query module
  cifs: Include linux/err.h for IS_ERR and PTR_ERR
  DNS: Make AFS go to the DNS for AFSDB records for unknown cells
  DNS: Separate out CIFS DNS Resolver code
  cifs: account for new creduid=0x%x parameter in spnego upcall string
  cifs: reduce false positives with inode aliasing serverino autodisable
  CIFS: Make cifs_convert_address() take a const src pointer and a length
  cifs: show features compiled in as part of DebugData
  cifs: update README

Fix up trivial conflicts in fs/cifs/cifsfs.c due to workqueue changes
  • Loading branch information
Linus Torvalds committed Aug 7, 2010
2 parents 3b7433b + 5227bbb commit 1fc7995
Show file tree
Hide file tree
Showing 24 changed files with 833 additions and 257 deletions.
146 changes: 146 additions & 0 deletions Documentation/networking/dns_resolver.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
===================
DNS Resolver Module
===================

Contents:

- Overview.
- Compilation.
- Setting up.
- Usage.
- Mechanism.
- Debugging.


========
OVERVIEW
========

The DNS resolver module provides a way for kernel services to make DNS queries
by way of requesting a key of key type dns_resolver. These queries are
upcalled to userspace through /sbin/request-key.

These routines must be supported by userspace tools dns.upcall, cifs.upcall and
request-key. It is under development and does not yet provide the full feature
set. The features it does support include:

(*) Implements the dns_resolver key_type to contact userspace.

It does not yet support the following AFS features:

(*) Dns query support for AFSDB resource record.

This code is extracted from the CIFS filesystem.


===========
COMPILATION
===========

The module should be enabled by turning on the kernel configuration options:

CONFIG_DNS_RESOLVER - tristate "DNS Resolver support"


==========
SETTING UP
==========

To set up this facility, the /etc/request-key.conf file must be altered so that
/sbin/request-key can appropriately direct the upcalls. For example, to handle
basic dname to IPv4/IPv6 address resolution, the following line should be
added:

#OP TYPE DESC CO-INFO PROGRAM ARG1 ARG2 ARG3 ...
#====== ============ ======= ======= ==========================
create dns_resolver * * /usr/sbin/cifs.upcall %k

To direct a query for query type 'foo', a line of the following should be added
before the more general line given above as the first match is the one taken.

create dns_resolver foo:* * /usr/sbin/dns.foo %k



=====
USAGE
=====

To make use of this facility, one of the following functions that are
implemented in the module can be called after doing:

#include <linux/dns_resolver.h>

(1) int dns_query(const char *type, const char *name, size_t namelen,
const char *options, char **_result, time_t *_expiry);

This is the basic access function. It looks for a cached DNS query and if
it doesn't find it, it upcalls to userspace to make a new DNS query, which
may then be cached. The key description is constructed as a string of the
form:

[<type>:]<name>

where <type> optionally specifies the particular upcall program to invoke,
and thus the type of query to do, and <name> specifies the string to be
looked up. The default query type is a straight hostname to IP address
set lookup.

The name parameter is not required to be a NUL-terminated string, and its
length should be given by the namelen argument.

The options parameter may be NULL or it may be a set of options
appropriate to the query type.

The return value is a string appropriate to the query type. For instance,
for the default query type it is just a list of comma-separated IPv4 and
IPv6 addresses. The caller must free the result.

The length of the result string is returned on success, and a negative
error code is returned otherwise. -EKEYREJECTED will be returned if the
DNS lookup failed.

If _expiry is non-NULL, the expiry time (TTL) of the result will be
returned also.


=========
MECHANISM
=========

The dnsresolver module registers a key type called "dns_resolver". Keys of
this type are used to transport and cache DNS lookup results from userspace.

When dns_query() is invoked, it calls request_key() to search the local
keyrings for a cached DNS result. If that fails to find one, it upcalls to
userspace to get a new result.

Upcalls to userspace are made through the request_key() upcall vector, and are
directed by means of configuration lines in /etc/request-key.conf that tell
/sbin/request-key what program to run to instantiate the key.

The upcall handler program is responsible for querying the DNS, processing the
result into a form suitable for passing to the keyctl_instantiate_key()
routine. This then passes the data to dns_resolver_instantiate() which strips
off and processes any options included in the data, and then attaches the
remainder of the string to the key as its payload.

The upcall handler program should set the expiry time on the key to that of the
lowest TTL of all the records it has extracted a result from. This means that
the key will be discarded and recreated when the data it holds has expired.

dns_query() returns a copy of the value attached to the key, or an error if
that is indicated instead.

See <file:Documentation/keys-request-key.txt> for further information about
request-key function.


=========
DEBUGGING
=========

Debugging messages can be turned on dynamically by writing a 1 into the
following file:

/sys/module/dnsresolver/parameters/debug
1 change: 1 addition & 0 deletions fs/afs/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ config AFS_FS
tristate "Andrew File System support (AFS) (EXPERIMENTAL)"
depends on INET && EXPERIMENTAL
select AF_RXRPC
select DNS_RESOLVER
help
If you say Y here, you will get an experimental Andrew File System
driver. It currently only supports unsecured read-only AFS access.
Expand Down
40 changes: 30 additions & 10 deletions fs/afs/cell.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <linux/slab.h>
#include <linux/key.h>
#include <linux/ctype.h>
#include <linux/dns_resolver.h>
#include <linux/sched.h>
#include <keys/rxrpc-type.h>
#include "internal.h"
Expand All @@ -36,15 +37,19 @@ static struct afs_cell *afs_cell_alloc(const char *name, char *vllist)
struct key *key;
size_t namelen;
char keyname[4 + AFS_MAXCELLNAME + 1], *cp, *dp, *next;
char *dvllist = NULL, *_vllist = NULL;
char delimiter = ':';
int ret;

_enter("%s,%s", name, vllist);

BUG_ON(!name); /* TODO: want to look up "this cell" in the cache */

namelen = strlen(name);
if (namelen > AFS_MAXCELLNAME)
if (namelen > AFS_MAXCELLNAME) {
_leave(" = -ENAMETOOLONG");
return ERR_PTR(-ENAMETOOLONG);
}

/* allocate and initialise a cell record */
cell = kzalloc(sizeof(struct afs_cell) + namelen + 1, GFP_KERNEL);
Expand All @@ -64,15 +69,31 @@ static struct afs_cell *afs_cell_alloc(const char *name, char *vllist)
INIT_LIST_HEAD(&cell->vl_list);
spin_lock_init(&cell->vl_lock);

/* if the ip address is invalid, try dns query */
if (!vllist || strlen(vllist) < 7) {
ret = dns_query("afsdb", name, namelen, "ipv4", &dvllist, NULL);
if (ret < 0) {
_leave(" = %d", ret);
return ERR_PTR(ret);
}
_vllist = dvllist;

/* change the delimiter for user-space reply */
delimiter = ',';

} else {
_vllist = vllist;
}

/* fill in the VL server list from the rest of the string */
do {
unsigned a, b, c, d;

next = strchr(vllist, ':');
next = strchr(_vllist, delimiter);
if (next)
*next++ = 0;

if (sscanf(vllist, "%u.%u.%u.%u", &a, &b, &c, &d) != 4)
if (sscanf(_vllist, "%u.%u.%u.%u", &a, &b, &c, &d) != 4)
goto bad_address;

if (a > 255 || b > 255 || c > 255 || d > 255)
Expand All @@ -81,7 +102,7 @@ static struct afs_cell *afs_cell_alloc(const char *name, char *vllist)
cell->vl_addrs[cell->vl_naddrs++].s_addr =
htonl((a << 24) | (b << 16) | (c << 8) | d);

} while (cell->vl_naddrs < AFS_CELL_MAX_ADDRS && (vllist = next));
} while (cell->vl_naddrs < AFS_CELL_MAX_ADDRS && (_vllist = next));

/* create a key to represent an anonymous user */
memcpy(keyname, "afs@", 4);
Expand Down Expand Up @@ -110,6 +131,7 @@ static struct afs_cell *afs_cell_alloc(const char *name, char *vllist)
ret = -EINVAL;
error:
key_put(cell->anonymous_key);
kfree(dvllist);
kfree(cell);
_leave(" = %d", ret);
return ERR_PTR(ret);
Expand Down Expand Up @@ -201,14 +223,12 @@ int afs_cell_init(char *rootcell)
}

cp = strchr(rootcell, ':');
if (!cp) {
printk(KERN_ERR "kAFS: no VL server IP addresses specified\n");
_leave(" = -EINVAL");
return -EINVAL;
}
if (!cp)
_debug("kAFS: no VL server IP addresses specified");
else
*cp++ = 0;

/* allocate a cell record for the root cell */
*cp++ = 0;
new_root = afs_cell_create(rootcell, cp);
if (IS_ERR(new_root)) {
_leave(" = %ld", PTR_ERR(new_root));
Expand Down
17 changes: 9 additions & 8 deletions fs/cifs/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -70,14 +70,14 @@ config CIFS_WEAK_PW_HASH
If unsure, say N.

config CIFS_UPCALL
bool "Kerberos/SPNEGO advanced session setup"
depends on CIFS && KEYS
help
Enables an upcall mechanism for CIFS which accesses
userspace helper utilities to provide SPNEGO packaged (RFC 4178)
Kerberos tickets which are needed to mount to certain secure servers
(for which more secure Kerberos authentication is required). If
unsure, say N.
bool "Kerberos/SPNEGO advanced session setup"
depends on CIFS && KEYS
select DNS_RESOLVER
help
Enables an upcall mechanism for CIFS which accesses userspace helper
utilities to provide SPNEGO packaged (RFC 4178) Kerberos tickets
which are needed to mount to certain secure servers (for which more
secure Kerberos authentication is required). If unsure, say N.

config CIFS_XATTR
bool "CIFS extended attributes"
Expand Down Expand Up @@ -121,6 +121,7 @@ config CIFS_DEBUG2
config CIFS_DFS_UPCALL
bool "DFS feature support"
depends on CIFS && KEYS
select DNS_RESOLVER
help
Distributed File System (DFS) support is used to access shares
transparently in an enterprise name space, even if the share
Expand Down
5 changes: 3 additions & 2 deletions fs/cifs/README
Original file line number Diff line number Diff line change
Expand Up @@ -568,8 +568,9 @@ module can be displayed via modinfo.
Misc /proc/fs/cifs Flags and Debug Info
=======================================
Informational pseudo-files:
DebugData Displays information about active CIFS sessions
and shares, as well as the cifs.ko version.
DebugData Displays information about active CIFS sessions and
shares, features enabled as well as the cifs.ko
version.
Stats Lists summary resource usage information as well as per
share statistics, if CONFIG_CIFS_STATS in enabled
in the kernel configuration.
Expand Down
25 changes: 25 additions & 0 deletions fs/cifs/cifs_debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,31 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
"Display Internal CIFS Data Structures for Debugging\n"
"---------------------------------------------------\n");
seq_printf(m, "CIFS Version %s\n", CIFS_VERSION);
seq_printf(m, "Features: ");
#ifdef CONFIG_CIFS_DFS_UPCALL
seq_printf(m, "dfs");
seq_putc(m, ' ');
#endif
#ifdef CONFIG_CIFS_FSCACHE
seq_printf(m, "fscache");
seq_putc(m, ' ');
#endif
#ifdef CONFIG_CIFS_WEAK_PW_HASH
seq_printf(m, "lanman");
seq_putc(m, ' ');
#endif
#ifdef CONFIG_CIFS_POSIX
seq_printf(m, "posix");
seq_putc(m, ' ');
#endif
#ifdef CONFIG_CIFS_UPCALL
seq_printf(m, "spnego");
seq_putc(m, ' ');
#endif
#ifdef CONFIG_CIFS_XATTR
seq_printf(m, "xattr");
#endif
seq_putc(m, '\n');
seq_printf(m, "Active VFS Requests: %d\n", GlobalTotalActiveXid);
seq_printf(m, "Servers:");

Expand Down
5 changes: 2 additions & 3 deletions fs/cifs/cifs_dfs_ref.c
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ char *cifs_compose_mount_options(const char *sb_mountdata,
}

rc = dns_resolve_server_name_to_ip(*devname, &srvIP);
if (rc != 0) {
if (rc < 0) {
cERROR(1, "%s: Failed to resolve server part of %s to IP: %d",
__func__, *devname, rc);
goto compose_mount_options_err;
Expand All @@ -150,8 +150,7 @@ char *cifs_compose_mount_options(const char *sb_mountdata,
* assuming that we have 'unc=' and 'ip=' in
* the original sb_mountdata
*/
md_len = strlen(sb_mountdata) + strlen(srvIP) +
strlen(ref->node_name) + 12;
md_len = strlen(sb_mountdata) + rc + strlen(ref->node_name) + 12;
mountdata = kzalloc(md_len+1, GFP_KERNEL);
if (mountdata == NULL) {
rc = -ENOMEM;
Expand Down
4 changes: 4 additions & 0 deletions fs/cifs/cifs_spnego.c
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,9 @@ struct key_type cifs_spnego_key_type = {
/* strlen of ";uid=0x" */
#define UID_KEY_LEN 7

/* strlen of ";creduid=0x" */
#define CREDUID_KEY_LEN 11

/* strlen of ";user=" */
#define USER_KEY_LEN 6

Expand All @@ -107,6 +110,7 @@ cifs_get_spnego_key(struct cifsSesInfo *sesInfo)
IP_KEY_LEN + INET6_ADDRSTRLEN +
MAX_MECH_STR_LEN +
UID_KEY_LEN + (sizeof(uid_t) * 2) +
CREDUID_KEY_LEN + (sizeof(uid_t) * 2) +
USER_KEY_LEN + strlen(sesInfo->userName) +
PID_KEY_LEN + (sizeof(pid_t) * 2) + 1;

Expand Down
Loading

0 comments on commit 1fc7995

Please sign in to comment.