aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc/auth_gss/svcauth_gss.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-05-03 13:59:39 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-05-03 13:59:39 -0400
commit1db772216f48978d5146b858586f6178433aad38 (patch)
tree4cb1f7345256c7a89c85b7a6157bbf16b944782e /net/sunrpc/auth_gss/svcauth_gss.c
parent86652188f345edec56b0074a65f6db17f16eb359 (diff)
parent676e4ebd5f2c3b4fd1d2bff79b68385c23c5c105 (diff)
Merge branch 'for-3.10' of git://linux-nfs.org/~bfields/linux
Pull nfsd changes from J Bruce Fields: "Highlights include: - Some more DRC cleanup and performance work from Jeff Layton - A gss-proxy upcall from Simo Sorce: currently krb5 mounts to the server using credentials from Active Directory often fail due to limitations of the svcgssd upcall interface. This replacement lifts those limitations. The existing upcall is still supported for backwards compatibility. - More NFSv4.1 support: at this point, if a user with a current client who upgrades from 4.0 to 4.1 should see no regressions. In theory we do everything a 4.1 server is required to do. Patches for a couple minor exceptions are ready for 3.11, and with those and some more testing I'd like to turn 4.1 on by default in 3.11." Fix up semantic conflict as per Stephen Rothwell and linux-next: Commit 030d794bf498 ("SUNRPC: Use gssproxy upcall for server RPCGSS authentication") adds two new users of "PDE(inode)->data", but we're supposed to use "PDE_DATA(inode)" instead since commit d9dda78bad87 ("procfs: new helper - PDE_DATA(inode)"). The old PDE() macro is no longer available since commit c30480b92cf4 ("proc: Make the PROC_I() and PDE() macros internal to procfs") * 'for-3.10' of git://linux-nfs.org/~bfields/linux: (60 commits) NFSD: SECINFO doesn't handle unsupported pseudoflavors correctly NFSD: Simplify GSS flavor encoding in nfsd4_do_encode_secinfo() nfsd: make symbol nfsd_reply_cache_shrinker static svcauth_gss: fix error return code in rsc_parse() nfsd4: don't remap EISDIR errors in rename svcrpc: fix gss-proxy to respect user namespaces SUNRPC: gssp_procedures[] can be static SUNRPC: define {create,destroy}_use_gss_proxy_proc_entry in !PROC case nfsd4: better error return to indicate SSV non-support nfsd: fix EXDEV checking in rename SUNRPC: Use gssproxy upcall for server RPCGSS authentication. SUNRPC: Add RPC based upcall mechanism for RPCGSS auth SUNRPC: conditionally return endtime from import_sec_context SUNRPC: allow disabling idle timeout SUNRPC: attempt AF_LOCAL connect on setup nfsd: Decode and send 64bit time values nfsd4: put_client_renew_locked can be static nfsd4: remove unused macro nfsd4: remove some useless code nfsd4: implement SEQ4_STATUS_RECALLABLE_STATE_REVOKED ...
Diffstat (limited to 'net/sunrpc/auth_gss/svcauth_gss.c')
-rw-r--r--net/sunrpc/auth_gss/svcauth_gss.c363
1 files changed, 352 insertions, 11 deletions
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
index c3ba570222dc..871c73c92165 100644
--- a/net/sunrpc/auth_gss/svcauth_gss.c
+++ b/net/sunrpc/auth_gss/svcauth_gss.c
@@ -48,8 +48,8 @@
48#include <linux/sunrpc/svcauth.h> 48#include <linux/sunrpc/svcauth.h>
49#include <linux/sunrpc/svcauth_gss.h> 49#include <linux/sunrpc/svcauth_gss.h>
50#include <linux/sunrpc/cache.h> 50#include <linux/sunrpc/cache.h>
51#include "gss_rpc_upcall.h"
51 52
52#include "../netns.h"
53 53
54#ifdef RPC_DEBUG 54#ifdef RPC_DEBUG
55# define RPCDBG_FACILITY RPCDBG_AUTH 55# define RPCDBG_FACILITY RPCDBG_AUTH
@@ -497,7 +497,8 @@ static int rsc_parse(struct cache_detail *cd,
497 len = qword_get(&mesg, buf, mlen); 497 len = qword_get(&mesg, buf, mlen);
498 if (len < 0) 498 if (len < 0)
499 goto out; 499 goto out;
500 status = gss_import_sec_context(buf, len, gm, &rsci.mechctx, GFP_KERNEL); 500 status = gss_import_sec_context(buf, len, gm, &rsci.mechctx,
501 NULL, GFP_KERNEL);
501 if (status) 502 if (status)
502 goto out; 503 goto out;
503 504
@@ -505,8 +506,10 @@ static int rsc_parse(struct cache_detail *cd,
505 len = qword_get(&mesg, buf, mlen); 506 len = qword_get(&mesg, buf, mlen);
506 if (len > 0) { 507 if (len > 0) {
507 rsci.cred.cr_principal = kstrdup(buf, GFP_KERNEL); 508 rsci.cred.cr_principal = kstrdup(buf, GFP_KERNEL);
508 if (!rsci.cred.cr_principal) 509 if (!rsci.cred.cr_principal) {
510 status = -ENOMEM;
509 goto out; 511 goto out;
512 }
510 } 513 }
511 514
512 } 515 }
@@ -987,13 +990,10 @@ gss_write_init_verf(struct cache_detail *cd, struct svc_rqst *rqstp,
987} 990}
988 991
989static inline int 992static inline int
990gss_read_verf(struct rpc_gss_wire_cred *gc, 993gss_read_common_verf(struct rpc_gss_wire_cred *gc,
991 struct kvec *argv, __be32 *authp, 994 struct kvec *argv, __be32 *authp,
992 struct xdr_netobj *in_handle, 995 struct xdr_netobj *in_handle)
993 struct xdr_netobj *in_token)
994{ 996{
995 struct xdr_netobj tmpobj;
996
997 /* Read the verifier; should be NULL: */ 997 /* Read the verifier; should be NULL: */
998 *authp = rpc_autherr_badverf; 998 *authp = rpc_autherr_badverf;
999 if (argv->iov_len < 2 * 4) 999 if (argv->iov_len < 2 * 4)
@@ -1009,6 +1009,23 @@ gss_read_verf(struct rpc_gss_wire_cred *gc,
1009 if (dup_netobj(in_handle, &gc->gc_ctx)) 1009 if (dup_netobj(in_handle, &gc->gc_ctx))
1010 return SVC_CLOSE; 1010 return SVC_CLOSE;
1011 *authp = rpc_autherr_badverf; 1011 *authp = rpc_autherr_badverf;
1012
1013 return 0;
1014}
1015
1016static inline int
1017gss_read_verf(struct rpc_gss_wire_cred *gc,
1018 struct kvec *argv, __be32 *authp,
1019 struct xdr_netobj *in_handle,
1020 struct xdr_netobj *in_token)
1021{
1022 struct xdr_netobj tmpobj;
1023 int res;
1024
1025 res = gss_read_common_verf(gc, argv, authp, in_handle);
1026 if (res)
1027 return res;
1028
1012 if (svc_safe_getnetobj(argv, &tmpobj)) { 1029 if (svc_safe_getnetobj(argv, &tmpobj)) {
1013 kfree(in_handle->data); 1030 kfree(in_handle->data);
1014 return SVC_DENIED; 1031 return SVC_DENIED;
@@ -1021,6 +1038,40 @@ gss_read_verf(struct rpc_gss_wire_cred *gc,
1021 return 0; 1038 return 0;
1022} 1039}
1023 1040
1041/* Ok this is really heavily depending on a set of semantics in
1042 * how rqstp is set up by svc_recv and pages laid down by the
1043 * server when reading a request. We are basically guaranteed that
1044 * the token lays all down linearly across a set of pages, starting
1045 * at iov_base in rq_arg.head[0] which happens to be the first of a
1046 * set of pages stored in rq_pages[].
1047 * rq_arg.head[0].iov_base will provide us the page_base to pass
1048 * to the upcall.
1049 */
1050static inline int
1051gss_read_proxy_verf(struct svc_rqst *rqstp,
1052 struct rpc_gss_wire_cred *gc, __be32 *authp,
1053 struct xdr_netobj *in_handle,
1054 struct gssp_in_token *in_token)
1055{
1056 struct kvec *argv = &rqstp->rq_arg.head[0];
1057 u32 inlen;
1058 int res;
1059
1060 res = gss_read_common_verf(gc, argv, authp, in_handle);
1061 if (res)
1062 return res;
1063
1064 inlen = svc_getnl(argv);
1065 if (inlen > (argv->iov_len + rqstp->rq_arg.page_len))
1066 return SVC_DENIED;
1067
1068 in_token->pages = rqstp->rq_pages;
1069 in_token->page_base = (ulong)argv->iov_base & ~PAGE_MASK;
1070 in_token->page_len = inlen;
1071
1072 return 0;
1073}
1074
1024static inline int 1075static inline int
1025gss_write_resv(struct kvec *resv, size_t size_limit, 1076gss_write_resv(struct kvec *resv, size_t size_limit,
1026 struct xdr_netobj *out_handle, struct xdr_netobj *out_token, 1077 struct xdr_netobj *out_handle, struct xdr_netobj *out_token,
@@ -1048,7 +1099,7 @@ gss_write_resv(struct kvec *resv, size_t size_limit,
1048 * the upcall results are available, write the verifier and result. 1099 * the upcall results are available, write the verifier and result.
1049 * Otherwise, drop the request pending an answer to the upcall. 1100 * Otherwise, drop the request pending an answer to the upcall.
1050 */ 1101 */
1051static int svcauth_gss_handle_init(struct svc_rqst *rqstp, 1102static int svcauth_gss_legacy_init(struct svc_rqst *rqstp,
1052 struct rpc_gss_wire_cred *gc, __be32 *authp) 1103 struct rpc_gss_wire_cred *gc, __be32 *authp)
1053{ 1104{
1054 struct kvec *argv = &rqstp->rq_arg.head[0]; 1105 struct kvec *argv = &rqstp->rq_arg.head[0];
@@ -1088,6 +1139,287 @@ out:
1088 return ret; 1139 return ret;
1089} 1140}
1090 1141
1142static int gss_proxy_save_rsc(struct cache_detail *cd,
1143 struct gssp_upcall_data *ud,
1144 uint64_t *handle)
1145{
1146 struct rsc rsci, *rscp = NULL;
1147 static atomic64_t ctxhctr;
1148 long long ctxh;
1149 struct gss_api_mech *gm = NULL;
1150 time_t expiry;
1151 int status = -EINVAL;
1152
1153 memset(&rsci, 0, sizeof(rsci));
1154 /* context handle */
1155 status = -ENOMEM;
1156 /* the handle needs to be just a unique id,
1157 * use a static counter */
1158 ctxh = atomic64_inc_return(&ctxhctr);
1159
1160 /* make a copy for the caller */
1161 *handle = ctxh;
1162
1163 /* make a copy for the rsc cache */
1164 if (dup_to_netobj(&rsci.handle, (char *)handle, sizeof(uint64_t)))
1165 goto out;
1166 rscp = rsc_lookup(cd, &rsci);
1167 if (!rscp)
1168 goto out;
1169
1170 /* creds */
1171 if (!ud->found_creds) {
1172 /* userspace seem buggy, we should always get at least a
1173 * mapping to nobody */
1174 dprintk("RPC: No creds found, marking Negative!\n");
1175 set_bit(CACHE_NEGATIVE, &rsci.h.flags);
1176 } else {
1177
1178 /* steal creds */
1179 rsci.cred = ud->creds;
1180 memset(&ud->creds, 0, sizeof(struct svc_cred));
1181
1182 status = -EOPNOTSUPP;
1183 /* get mech handle from OID */
1184 gm = gss_mech_get_by_OID(&ud->mech_oid);
1185 if (!gm)
1186 goto out;
1187
1188 status = -EINVAL;
1189 /* mech-specific data: */
1190 status = gss_import_sec_context(ud->out_handle.data,
1191 ud->out_handle.len,
1192 gm, &rsci.mechctx,
1193 &expiry, GFP_KERNEL);
1194 if (status)
1195 goto out;
1196 }
1197
1198 rsci.h.expiry_time = expiry;
1199 rscp = rsc_update(cd, &rsci, rscp);
1200 status = 0;
1201out:
1202 gss_mech_put(gm);
1203 rsc_free(&rsci);
1204 if (rscp)
1205 cache_put(&rscp->h, cd);
1206 else
1207 status = -ENOMEM;
1208 return status;
1209}
1210
1211static int svcauth_gss_proxy_init(struct svc_rqst *rqstp,
1212 struct rpc_gss_wire_cred *gc, __be32 *authp)
1213{
1214 struct kvec *resv = &rqstp->rq_res.head[0];
1215 struct xdr_netobj cli_handle;
1216 struct gssp_upcall_data ud;
1217 uint64_t handle;
1218 int status;
1219 int ret;
1220 struct net *net = rqstp->rq_xprt->xpt_net;
1221 struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
1222
1223 memset(&ud, 0, sizeof(ud));
1224 ret = gss_read_proxy_verf(rqstp, gc, authp,
1225 &ud.in_handle, &ud.in_token);
1226 if (ret)
1227 return ret;
1228
1229 ret = SVC_CLOSE;
1230
1231 /* Perform synchronous upcall to gss-proxy */
1232 status = gssp_accept_sec_context_upcall(net, &ud);
1233 if (status)
1234 goto out;
1235
1236 dprintk("RPC: svcauth_gss: gss major status = %d\n",
1237 ud.major_status);
1238
1239 switch (ud.major_status) {
1240 case GSS_S_CONTINUE_NEEDED:
1241 cli_handle = ud.out_handle;
1242 break;
1243 case GSS_S_COMPLETE:
1244 status = gss_proxy_save_rsc(sn->rsc_cache, &ud, &handle);
1245 if (status)
1246 goto out;
1247 cli_handle.data = (u8 *)&handle;
1248 cli_handle.len = sizeof(handle);
1249 break;
1250 default:
1251 ret = SVC_CLOSE;
1252 goto out;
1253 }
1254
1255 /* Got an answer to the upcall; use it: */
1256 if (gss_write_init_verf(sn->rsc_cache, rqstp,
1257 &cli_handle, &ud.major_status))
1258 goto out;
1259 if (gss_write_resv(resv, PAGE_SIZE,
1260 &cli_handle, &ud.out_token,
1261 ud.major_status, ud.minor_status))
1262 goto out;
1263
1264 ret = SVC_COMPLETE;
1265out:
1266 gssp_free_upcall_data(&ud);
1267 return ret;
1268}
1269
1270DEFINE_SPINLOCK(use_gssp_lock);
1271
1272static bool use_gss_proxy(struct net *net)
1273{
1274 struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
1275
1276 if (sn->use_gss_proxy != -1)
1277 return sn->use_gss_proxy;
1278 spin_lock(&use_gssp_lock);
1279 /*
1280 * If you wanted gss-proxy, you should have said so before
1281 * starting to accept requests:
1282 */
1283 sn->use_gss_proxy = 0;
1284 spin_unlock(&use_gssp_lock);
1285 return 0;
1286}
1287
1288#ifdef CONFIG_PROC_FS
1289
1290static bool set_gss_proxy(struct net *net, int type)
1291{
1292 struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
1293 int ret = 0;
1294
1295 WARN_ON_ONCE(type != 0 && type != 1);
1296 spin_lock(&use_gssp_lock);
1297 if (sn->use_gss_proxy == -1 || sn->use_gss_proxy == type)
1298 sn->use_gss_proxy = type;
1299 else
1300 ret = -EBUSY;
1301 spin_unlock(&use_gssp_lock);
1302 wake_up(&sn->gssp_wq);
1303 return ret;
1304}
1305
1306static inline bool gssp_ready(struct sunrpc_net *sn)
1307{
1308 switch (sn->use_gss_proxy) {
1309 case -1:
1310 return false;
1311 case 0:
1312 return true;
1313 case 1:
1314 return sn->gssp_clnt;
1315 }
1316 WARN_ON_ONCE(1);
1317 return false;
1318}
1319
1320static int wait_for_gss_proxy(struct net *net)
1321{
1322 struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
1323
1324 return wait_event_interruptible(sn->gssp_wq, gssp_ready(sn));
1325}
1326
1327
1328static ssize_t write_gssp(struct file *file, const char __user *buf,
1329 size_t count, loff_t *ppos)
1330{
1331 struct net *net = PDE_DATA(file->f_path.dentry->d_inode);
1332 char tbuf[20];
1333 unsigned long i;
1334 int res;
1335
1336 if (*ppos || count > sizeof(tbuf)-1)
1337 return -EINVAL;
1338 if (copy_from_user(tbuf, buf, count))
1339 return -EFAULT;
1340
1341 tbuf[count] = 0;
1342 res = kstrtoul(tbuf, 0, &i);
1343 if (res)
1344 return res;
1345 if (i != 1)
1346 return -EINVAL;
1347 res = set_gss_proxy(net, 1);
1348 if (res)
1349 return res;
1350 res = set_gssp_clnt(net);
1351 if (res)
1352 return res;
1353 return count;
1354}
1355
1356static ssize_t read_gssp(struct file *file, char __user *buf,
1357 size_t count, loff_t *ppos)
1358{
1359 struct net *net = PDE_DATA(file->f_path.dentry->d_inode);
1360 unsigned long p = *ppos;
1361 char tbuf[10];
1362 size_t len;
1363 int ret;
1364
1365 ret = wait_for_gss_proxy(net);
1366 if (ret)
1367 return ret;
1368
1369 snprintf(tbuf, sizeof(tbuf), "%d\n", use_gss_proxy(net));
1370 len = strlen(tbuf);
1371 if (p >= len)
1372 return 0;
1373 len -= p;
1374 if (len > count)
1375 len = count;
1376 if (copy_to_user(buf, (void *)(tbuf+p), len))
1377 return -EFAULT;
1378 *ppos += len;
1379 return len;
1380}
1381
1382static const struct file_operations use_gss_proxy_ops = {
1383 .open = nonseekable_open,
1384 .write = write_gssp,
1385 .read = read_gssp,
1386};
1387
1388static int create_use_gss_proxy_proc_entry(struct net *net)
1389{
1390 struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
1391 struct proc_dir_entry **p = &sn->use_gssp_proc;
1392
1393 sn->use_gss_proxy = -1;
1394 *p = proc_create_data("use-gss-proxy", S_IFREG|S_IRUSR|S_IWUSR,
1395 sn->proc_net_rpc,
1396 &use_gss_proxy_ops, net);
1397 if (!*p)
1398 return -ENOMEM;
1399 init_gssp_clnt(sn);
1400 return 0;
1401}
1402
1403static void destroy_use_gss_proxy_proc_entry(struct net *net)
1404{
1405 struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
1406
1407 if (sn->use_gssp_proc) {
1408 remove_proc_entry("use-gss-proxy", sn->proc_net_rpc);
1409 clear_gssp_clnt(sn);
1410 }
1411}
1412#else /* CONFIG_PROC_FS */
1413
1414static int create_use_gss_proxy_proc_entry(struct net *net)
1415{
1416 return 0;
1417}
1418
1419static void destroy_use_gss_proxy_proc_entry(struct net *net) {}
1420
1421#endif /* CONFIG_PROC_FS */
1422
1091/* 1423/*
1092 * Accept an rpcsec packet. 1424 * Accept an rpcsec packet.
1093 * If context establishment, punt to user space 1425 * If context establishment, punt to user space
@@ -1154,7 +1486,10 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp)
1154 switch (gc->gc_proc) { 1486 switch (gc->gc_proc) {
1155 case RPC_GSS_PROC_INIT: 1487 case RPC_GSS_PROC_INIT:
1156 case RPC_GSS_PROC_CONTINUE_INIT: 1488 case RPC_GSS_PROC_CONTINUE_INIT:
1157 return svcauth_gss_handle_init(rqstp, gc, authp); 1489 if (use_gss_proxy(SVC_NET(rqstp)))
1490 return svcauth_gss_proxy_init(rqstp, gc, authp);
1491 else
1492 return svcauth_gss_legacy_init(rqstp, gc, authp);
1158 case RPC_GSS_PROC_DATA: 1493 case RPC_GSS_PROC_DATA:
1159 case RPC_GSS_PROC_DESTROY: 1494 case RPC_GSS_PROC_DESTROY:
1160 /* Look up the context, and check the verifier: */ 1495 /* Look up the context, and check the verifier: */
@@ -1531,7 +1866,12 @@ gss_svc_init_net(struct net *net)
1531 rv = rsi_cache_create_net(net); 1866 rv = rsi_cache_create_net(net);
1532 if (rv) 1867 if (rv)
1533 goto out1; 1868 goto out1;
1869 rv = create_use_gss_proxy_proc_entry(net);
1870 if (rv)
1871 goto out2;
1534 return 0; 1872 return 0;
1873out2:
1874 destroy_use_gss_proxy_proc_entry(net);
1535out1: 1875out1:
1536 rsc_cache_destroy_net(net); 1876 rsc_cache_destroy_net(net);
1537 return rv; 1877 return rv;
@@ -1540,6 +1880,7 @@ out1:
1540void 1880void
1541gss_svc_shutdown_net(struct net *net) 1881gss_svc_shutdown_net(struct net *net)
1542{ 1882{
1883 destroy_use_gss_proxy_proc_entry(net);
1543 rsi_cache_destroy_net(net); 1884 rsi_cache_destroy_net(net);
1544 rsc_cache_destroy_net(net); 1885 rsc_cache_destroy_net(net);
1545} 1886}