aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/sunrpc/auth_gss/gss_rpc_upcall.c2
-rw-r--r--net/sunrpc/auth_gss/svcauth_gss.c347
-rw-r--r--net/sunrpc/netns.h3
3 files changed, 343 insertions, 9 deletions
diff --git a/net/sunrpc/auth_gss/gss_rpc_upcall.c b/net/sunrpc/auth_gss/gss_rpc_upcall.c
index 2d33ddfe74e5..3f874d704859 100644
--- a/net/sunrpc/auth_gss/gss_rpc_upcall.c
+++ b/net/sunrpc/auth_gss/gss_rpc_upcall.c
@@ -137,6 +137,7 @@ void init_gssp_clnt(struct sunrpc_net *sn)
137{ 137{
138 mutex_init(&sn->gssp_lock); 138 mutex_init(&sn->gssp_lock);
139 sn->gssp_clnt = NULL; 139 sn->gssp_clnt = NULL;
140 init_waitqueue_head(&sn->gssp_wq);
140} 141}
141 142
142int set_gssp_clnt(struct net *net) 143int set_gssp_clnt(struct net *net)
@@ -153,6 +154,7 @@ int set_gssp_clnt(struct net *net)
153 sn->gssp_clnt = clnt; 154 sn->gssp_clnt = clnt;
154 } 155 }
155 mutex_unlock(&sn->gssp_lock); 156 mutex_unlock(&sn->gssp_lock);
157 wake_up(&sn->gssp_wq);
156 return ret; 158 return ret;
157} 159}
158 160
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
index 20eedecc35f8..58f5bc329408 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
@@ -988,13 +988,10 @@ gss_write_init_verf(struct cache_detail *cd, struct svc_rqst *rqstp,
988} 988}
989 989
990static inline int 990static inline int
991gss_read_verf(struct rpc_gss_wire_cred *gc, 991gss_read_common_verf(struct rpc_gss_wire_cred *gc,
992 struct kvec *argv, __be32 *authp, 992 struct kvec *argv, __be32 *authp,
993 struct xdr_netobj *in_handle, 993 struct xdr_netobj *in_handle)
994 struct xdr_netobj *in_token)
995{ 994{
996 struct xdr_netobj tmpobj;
997
998 /* Read the verifier; should be NULL: */ 995 /* Read the verifier; should be NULL: */
999 *authp = rpc_autherr_badverf; 996 *authp = rpc_autherr_badverf;
1000 if (argv->iov_len < 2 * 4) 997 if (argv->iov_len < 2 * 4)
@@ -1010,6 +1007,23 @@ gss_read_verf(struct rpc_gss_wire_cred *gc,
1010 if (dup_netobj(in_handle, &gc->gc_ctx)) 1007 if (dup_netobj(in_handle, &gc->gc_ctx))
1011 return SVC_CLOSE; 1008 return SVC_CLOSE;
1012 *authp = rpc_autherr_badverf; 1009 *authp = rpc_autherr_badverf;
1010
1011 return 0;
1012}
1013
1014static inline int
1015gss_read_verf(struct rpc_gss_wire_cred *gc,
1016 struct kvec *argv, __be32 *authp,
1017 struct xdr_netobj *in_handle,
1018 struct xdr_netobj *in_token)
1019{
1020 struct xdr_netobj tmpobj;
1021 int res;
1022
1023 res = gss_read_common_verf(gc, argv, authp, in_handle);
1024 if (res)
1025 return res;
1026
1013 if (svc_safe_getnetobj(argv, &tmpobj)) { 1027 if (svc_safe_getnetobj(argv, &tmpobj)) {
1014 kfree(in_handle->data); 1028 kfree(in_handle->data);
1015 return SVC_DENIED; 1029 return SVC_DENIED;
@@ -1022,6 +1036,40 @@ gss_read_verf(struct rpc_gss_wire_cred *gc,
1022 return 0; 1036 return 0;
1023} 1037}
1024 1038
1039/* Ok this is really heavily depending on a set of semantics in
1040 * how rqstp is set up by svc_recv and pages laid down by the
1041 * server when reading a request. We are basically guaranteed that
1042 * the token lays all down linearly across a set of pages, starting
1043 * at iov_base in rq_arg.head[0] which happens to be the first of a
1044 * set of pages stored in rq_pages[].
1045 * rq_arg.head[0].iov_base will provide us the page_base to pass
1046 * to the upcall.
1047 */
1048static inline int
1049gss_read_proxy_verf(struct svc_rqst *rqstp,
1050 struct rpc_gss_wire_cred *gc, __be32 *authp,
1051 struct xdr_netobj *in_handle,
1052 struct gssp_in_token *in_token)
1053{
1054 struct kvec *argv = &rqstp->rq_arg.head[0];
1055 u32 inlen;
1056 int res;
1057
1058 res = gss_read_common_verf(gc, argv, authp, in_handle);
1059 if (res)
1060 return res;
1061
1062 inlen = svc_getnl(argv);
1063 if (inlen > (argv->iov_len + rqstp->rq_arg.page_len))
1064 return SVC_DENIED;
1065
1066 in_token->pages = rqstp->rq_pages;
1067 in_token->page_base = (ulong)argv->iov_base & ~PAGE_MASK;
1068 in_token->page_len = inlen;
1069
1070 return 0;
1071}
1072
1025static inline int 1073static inline int
1026gss_write_resv(struct kvec *resv, size_t size_limit, 1074gss_write_resv(struct kvec *resv, size_t size_limit,
1027 struct xdr_netobj *out_handle, struct xdr_netobj *out_token, 1075 struct xdr_netobj *out_handle, struct xdr_netobj *out_token,
@@ -1049,7 +1097,7 @@ gss_write_resv(struct kvec *resv, size_t size_limit,
1049 * the upcall results are available, write the verifier and result. 1097 * the upcall results are available, write the verifier and result.
1050 * Otherwise, drop the request pending an answer to the upcall. 1098 * Otherwise, drop the request pending an answer to the upcall.
1051 */ 1099 */
1052static int svcauth_gss_handle_init(struct svc_rqst *rqstp, 1100static int svcauth_gss_legacy_init(struct svc_rqst *rqstp,
1053 struct rpc_gss_wire_cred *gc, __be32 *authp) 1101 struct rpc_gss_wire_cred *gc, __be32 *authp)
1054{ 1102{
1055 struct kvec *argv = &rqstp->rq_arg.head[0]; 1103 struct kvec *argv = &rqstp->rq_arg.head[0];
@@ -1089,6 +1137,278 @@ out:
1089 return ret; 1137 return ret;
1090} 1138}
1091 1139
1140static int gss_proxy_save_rsc(struct cache_detail *cd,
1141 struct gssp_upcall_data *ud,
1142 uint64_t *handle)
1143{
1144 struct rsc rsci, *rscp = NULL;
1145 static atomic64_t ctxhctr;
1146 long long ctxh;
1147 struct gss_api_mech *gm = NULL;
1148 time_t expiry;
1149 int status = -EINVAL;
1150
1151 memset(&rsci, 0, sizeof(rsci));
1152 /* context handle */
1153 status = -ENOMEM;
1154 /* the handle needs to be just a unique id,
1155 * use a static counter */
1156 ctxh = atomic64_inc_return(&ctxhctr);
1157
1158 /* make a copy for the caller */
1159 *handle = ctxh;
1160
1161 /* make a copy for the rsc cache */
1162 if (dup_to_netobj(&rsci.handle, (char *)handle, sizeof(uint64_t)))
1163 goto out;
1164 rscp = rsc_lookup(cd, &rsci);
1165 if (!rscp)
1166 goto out;
1167
1168 /* creds */
1169 if (!ud->found_creds) {
1170 /* userspace seem buggy, we should always get at least a
1171 * mapping to nobody */
1172 dprintk("RPC: No creds found, marking Negative!\n");
1173 set_bit(CACHE_NEGATIVE, &rsci.h.flags);
1174 } else {
1175
1176 /* steal creds */
1177 rsci.cred = ud->creds;
1178 memset(&ud->creds, 0, sizeof(struct svc_cred));
1179
1180 status = -EOPNOTSUPP;
1181 /* get mech handle from OID */
1182 gm = gss_mech_get_by_OID(&ud->mech_oid);
1183 if (!gm)
1184 goto out;
1185
1186 status = -EINVAL;
1187 /* mech-specific data: */
1188 status = gss_import_sec_context(ud->out_handle.data,
1189 ud->out_handle.len,
1190 gm, &rsci.mechctx,
1191 &expiry, GFP_KERNEL);
1192 if (status)
1193 goto out;
1194 }
1195
1196 rsci.h.expiry_time = expiry;
1197 rscp = rsc_update(cd, &rsci, rscp);
1198 status = 0;
1199out:
1200 gss_mech_put(gm);
1201 rsc_free(&rsci);
1202 if (rscp)
1203 cache_put(&rscp->h, cd);
1204 else
1205 status = -ENOMEM;
1206 return status;
1207}
1208
1209static int svcauth_gss_proxy_init(struct svc_rqst *rqstp,
1210 struct rpc_gss_wire_cred *gc, __be32 *authp)
1211{
1212 struct kvec *resv = &rqstp->rq_res.head[0];
1213 struct xdr_netobj cli_handle;
1214 struct gssp_upcall_data ud;
1215 uint64_t handle;
1216 int status;
1217 int ret;
1218 struct net *net = rqstp->rq_xprt->xpt_net;
1219 struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
1220
1221 memset(&ud, 0, sizeof(ud));
1222 ret = gss_read_proxy_verf(rqstp, gc, authp,
1223 &ud.in_handle, &ud.in_token);
1224 if (ret)
1225 return ret;
1226
1227 ret = SVC_CLOSE;
1228
1229 /* Perform synchronous upcall to gss-proxy */
1230 status = gssp_accept_sec_context_upcall(net, &ud);
1231 if (status)
1232 goto out;
1233
1234 dprintk("RPC: svcauth_gss: gss major status = %d\n",
1235 ud.major_status);
1236
1237 switch (ud.major_status) {
1238 case GSS_S_CONTINUE_NEEDED:
1239 cli_handle = ud.out_handle;
1240 break;
1241 case GSS_S_COMPLETE:
1242 status = gss_proxy_save_rsc(sn->rsc_cache, &ud, &handle);
1243 if (status)
1244 goto out;
1245 cli_handle.data = (u8 *)&handle;
1246 cli_handle.len = sizeof(handle);
1247 break;
1248 default:
1249 ret = SVC_CLOSE;
1250 goto out;
1251 }
1252
1253 /* Got an answer to the upcall; use it: */
1254 if (gss_write_init_verf(sn->rsc_cache, rqstp,
1255 &cli_handle, &ud.major_status))
1256 goto out;
1257 if (gss_write_resv(resv, PAGE_SIZE,
1258 &cli_handle, &ud.out_token,
1259 ud.major_status, ud.minor_status))
1260 goto out;
1261
1262 ret = SVC_COMPLETE;
1263out:
1264 gssp_free_upcall_data(&ud);
1265 return ret;
1266}
1267
1268DEFINE_SPINLOCK(use_gssp_lock);
1269
1270static bool use_gss_proxy(struct net *net)
1271{
1272 struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
1273
1274 if (sn->use_gss_proxy != -1)
1275 return sn->use_gss_proxy;
1276 spin_lock(&use_gssp_lock);
1277 /*
1278 * If you wanted gss-proxy, you should have said so before
1279 * starting to accept requests:
1280 */
1281 sn->use_gss_proxy = 0;
1282 spin_unlock(&use_gssp_lock);
1283 return 0;
1284}
1285
1286static bool set_gss_proxy(struct net *net, int type)
1287{
1288 struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
1289 int ret = 0;
1290
1291 WARN_ON_ONCE(type != 0 && type != 1);
1292 spin_lock(&use_gssp_lock);
1293 if (sn->use_gss_proxy == -1 || sn->use_gss_proxy == type)
1294 sn->use_gss_proxy = type;
1295 else
1296 ret = -EBUSY;
1297 spin_unlock(&use_gssp_lock);
1298 wake_up(&sn->gssp_wq);
1299 return ret;
1300}
1301
1302static inline bool gssp_ready(struct sunrpc_net *sn)
1303{
1304 switch (sn->use_gss_proxy) {
1305 case -1:
1306 return false;
1307 case 0:
1308 return true;
1309 case 1:
1310 return sn->gssp_clnt;
1311 }
1312 WARN_ON_ONCE(1);
1313 return false;
1314}
1315
1316static int wait_for_gss_proxy(struct net *net)
1317{
1318 struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
1319
1320 return wait_event_interruptible(sn->gssp_wq, gssp_ready(sn));
1321}
1322
1323#ifdef CONFIG_PROC_FS
1324
1325static ssize_t write_gssp(struct file *file, const char __user *buf,
1326 size_t count, loff_t *ppos)
1327{
1328 struct net *net = PDE(file->f_path.dentry->d_inode)->data;
1329 char tbuf[20];
1330 unsigned long i;
1331 int res;
1332
1333 if (*ppos || count > sizeof(tbuf)-1)
1334 return -EINVAL;
1335 if (copy_from_user(tbuf, buf, count))
1336 return -EFAULT;
1337
1338 tbuf[count] = 0;
1339 res = kstrtoul(tbuf, 0, &i);
1340 if (res)
1341 return res;
1342 if (i != 1)
1343 return -EINVAL;
1344 res = set_gss_proxy(net, 1);
1345 if (res)
1346 return res;
1347 res = set_gssp_clnt(net);
1348 if (res)
1349 return res;
1350 return count;
1351}
1352
1353static ssize_t read_gssp(struct file *file, char __user *buf,
1354 size_t count, loff_t *ppos)
1355{
1356 struct net *net = PDE(file->f_path.dentry->d_inode)->data;
1357 unsigned long p = *ppos;
1358 char tbuf[10];
1359 size_t len;
1360 int ret;
1361
1362 ret = wait_for_gss_proxy(net);
1363 if (ret)
1364 return ret;
1365
1366 snprintf(tbuf, sizeof(tbuf), "%d\n", use_gss_proxy(net));
1367 len = strlen(tbuf);
1368 if (p >= len)
1369 return 0;
1370 len -= p;
1371 if (len > count)
1372 len = count;
1373 if (copy_to_user(buf, (void *)(tbuf+p), len))
1374 return -EFAULT;
1375 *ppos += len;
1376 return len;
1377}
1378
1379static const struct file_operations use_gss_proxy_ops = {
1380 .open = nonseekable_open,
1381 .write = write_gssp,
1382 .read = read_gssp,
1383};
1384
1385static int create_use_gss_proxy_proc_entry(struct net *net)
1386{
1387 struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
1388 struct proc_dir_entry **p = &sn->use_gssp_proc;
1389
1390 sn->use_gss_proxy = -1;
1391 *p = proc_create_data("use-gss-proxy", S_IFREG|S_IRUSR|S_IWUSR,
1392 sn->proc_net_rpc,
1393 &use_gss_proxy_ops, net);
1394 if (!*p)
1395 return -ENOMEM;
1396 init_gssp_clnt(sn);
1397 return 0;
1398}
1399
1400static void destroy_use_gss_proxy_proc_entry(struct net *net)
1401{
1402 struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
1403
1404 if (sn->use_gssp_proc) {
1405 remove_proc_entry("use-gss-proxy", sn->proc_net_rpc);
1406 clear_gssp_clnt(sn);
1407 }
1408}
1409
1410#endif /* CONFIG_PROC_FS */
1411
1092/* 1412/*
1093 * Accept an rpcsec packet. 1413 * Accept an rpcsec packet.
1094 * If context establishment, punt to user space 1414 * If context establishment, punt to user space
@@ -1155,7 +1475,10 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp)
1155 switch (gc->gc_proc) { 1475 switch (gc->gc_proc) {
1156 case RPC_GSS_PROC_INIT: 1476 case RPC_GSS_PROC_INIT:
1157 case RPC_GSS_PROC_CONTINUE_INIT: 1477 case RPC_GSS_PROC_CONTINUE_INIT:
1158 return svcauth_gss_handle_init(rqstp, gc, authp); 1478 if (use_gss_proxy(SVC_NET(rqstp)))
1479 return svcauth_gss_proxy_init(rqstp, gc, authp);
1480 else
1481 return svcauth_gss_legacy_init(rqstp, gc, authp);
1159 case RPC_GSS_PROC_DATA: 1482 case RPC_GSS_PROC_DATA:
1160 case RPC_GSS_PROC_DESTROY: 1483 case RPC_GSS_PROC_DESTROY:
1161 /* Look up the context, and check the verifier: */ 1484 /* Look up the context, and check the verifier: */
@@ -1530,7 +1853,12 @@ gss_svc_init_net(struct net *net)
1530 rv = rsi_cache_create_net(net); 1853 rv = rsi_cache_create_net(net);
1531 if (rv) 1854 if (rv)
1532 goto out1; 1855 goto out1;
1856 rv = create_use_gss_proxy_proc_entry(net);
1857 if (rv)
1858 goto out2;
1533 return 0; 1859 return 0;
1860out2:
1861 destroy_use_gss_proxy_proc_entry(net);
1534out1: 1862out1:
1535 rsc_cache_destroy_net(net); 1863 rsc_cache_destroy_net(net);
1536 return rv; 1864 return rv;
@@ -1539,6 +1867,7 @@ out1:
1539void 1867void
1540gss_svc_shutdown_net(struct net *net) 1868gss_svc_shutdown_net(struct net *net)
1541{ 1869{
1870 destroy_use_gss_proxy_proc_entry(net);
1542 rsi_cache_destroy_net(net); 1871 rsi_cache_destroy_net(net);
1543 rsc_cache_destroy_net(net); 1872 rsc_cache_destroy_net(net);
1544} 1873}
diff --git a/net/sunrpc/netns.h b/net/sunrpc/netns.h
index e9f8895d70ca..7111a4c9113b 100644
--- a/net/sunrpc/netns.h
+++ b/net/sunrpc/netns.h
@@ -25,7 +25,10 @@ struct sunrpc_net {
25 unsigned int rpcb_users; 25 unsigned int rpcb_users;
26 26
27 struct mutex gssp_lock; 27 struct mutex gssp_lock;
28 wait_queue_head_t gssp_wq;
28 struct rpc_clnt *gssp_clnt; 29 struct rpc_clnt *gssp_clnt;
30 int use_gss_proxy;
31 struct proc_dir_entry *use_gssp_proc;
29}; 32};
30 33
31extern int sunrpc_net_id; 34extern int sunrpc_net_id;