X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Fsec%2Fgss%2Fsec_gss.c;h=8bd4f0261932ef5a564f4df5f4b2883d616b85c4;hb=44f3d772c1ace979163c52b70ec392b81b45e39c;hp=7c8ce34e8065d12da7d7e87aa5261e311d70f9a1;hpb=29fc8c9200376c447fd26f82585ac9e45ca86414;p=fs%2Flustre-release.git diff --git a/lustre/sec/gss/sec_gss.c b/lustre/sec/gss/sec_gss.c index 7c8ce34..8bd4f02 100644 --- a/lustre/sec/gss/sec_gss.c +++ b/lustre/sec/gss/sec_gss.c @@ -76,10 +76,13 @@ struct rpc_clnt; #include "gss_internal.h" #include "gss_api.h" -#define GSS_CREDCACHE_EXPIRE (60) /* 1 minute */ +#define GSS_CREDCACHE_EXPIRE (30 * 60) /* 30 minute */ +/* not used now */ +#if 0 #define GSS_CRED_EXPIRE (8 * 60 * 60) /* 8 hours */ #define GSS_CRED_SIGN_SIZE (1024) #define GSS_CRED_VERIFY_SIZE (56) +#endif #define LUSTRE_PIPEDIR "/lustre" @@ -88,10 +91,11 @@ struct rpc_clnt; **********************************************/ #define SECINIT_RPC_TIMEOUT (30) -#define SECFINI_RPC_TIMEOUT (30) +#define SECFINI_RPC_TIMEOUT (10) static int secinit_compose_request(struct obd_import *imp, char *buf, int bufsize, + int lustre_srv, uid_t uid, gid_t gid, long token_size, char __user *token) @@ -112,10 +116,9 @@ static int secinit_compose_request(struct obd_import *imp, /* security wire hdr */ hdr = buf_to_sec_hdr(buf); - hdr->flavor = cpu_to_le32(PTLRPC_SEC_GSS); - hdr->sectype = cpu_to_le32(PTLRPC_SEC_TYPE_NONE); + hdr->flavor = cpu_to_le32(PTLRPCS_FLVR_GSS_NONE); hdr->msg_len = cpu_to_le32(lmsg_size); - hdr->sec_len = cpu_to_le32(7 * 4 + token_size); + hdr->sec_len = cpu_to_le32(8 * 4 + token_size); /* lustre message & secdesc */ lmsg = buf_to_lustre_msg(buf); @@ -136,12 +139,15 @@ static int secinit_compose_request(struct obd_import *imp, /* gss hdr */ *p++ = cpu_to_le32(PTLRPC_SEC_GSS_VERSION); /* gss version */ - *p++ = cpu_to_le32(PTLRPC_SEC_GSS_KRB5I); /* subflavor */ - *p++ = cpu_to_le32(PTLRPC_GSS_PROC_INIT); /* proc */ + *p++ = cpu_to_le32(PTLRPCS_FLVR_KRB5I); /* subflavor */ + *p++ = cpu_to_le32(PTLRPCS_GSS_PROC_INIT); /* proc */ *p++ = cpu_to_le32(0); /* seq */ - *p++ = cpu_to_le32(PTLRPC_GSS_SVC_NONE); /* service */ + *p++ = cpu_to_le32(PTLRPCS_GSS_SVC_NONE); /* service */ *p++ = cpu_to_le32(0); /* context handle */ + /* plus lustre svc type */ + *p++ = cpu_to_le32(lustre_srv); + /* now the token part */ *p++ = cpu_to_le32((__u32) token_size); LASSERT(((char *)p - buf) + token_size <= bufsize); @@ -171,7 +177,6 @@ static int secinit_parse_reply(char *repbuf, int replen, } hdr->flavor = le32_to_cpu(hdr->flavor); - hdr->sectype = le32_to_cpu(hdr->sectype); hdr->msg_len = le32_to_cpu(hdr->msg_len); hdr->sec_len = le32_to_cpu(hdr->sec_len); @@ -179,8 +184,7 @@ static int secinit_parse_reply(char *repbuf, int replen, sec_len = le32_to_cpu(p[3]); /* sanity checks */ - if (hdr->flavor != PTLRPC_SEC_GSS || - hdr->sectype != PTLRPC_SEC_TYPE_NONE) { + if (hdr->flavor != PTLRPCS_FLVR_GSS_NONE) { CERROR("unexpected reply\n"); return -EINVAL; } @@ -245,6 +249,7 @@ static int secinit_parse_reply(char *repbuf, int replen, struct lgssd_ioctl_param { int version; /* in */ char *uuid; /* in */ + int lustre_svc; /* in */ uid_t uid; /* in */ gid_t gid; /* in */ long send_token_size;/* in */ @@ -258,6 +263,7 @@ struct lgssd_ioctl_param { static int gss_send_secinit_rpc(__user char *buffer, unsigned long count) { struct obd_import *imp; + struct ptlrpc_request *request = NULL; struct lgssd_ioctl_param param; const int reqbuf_size = 1024; const int repbuf_size = 1024; @@ -268,11 +274,14 @@ static int gss_send_secinit_rpc(__user char *buffer, unsigned long count) int rc, reqlen, replen; if (count != sizeof(param)) { - CERROR("partial write\n"); + CERROR("ioctl size %lu, expect %d, please check lgssd version\n", + count, sizeof(param)); RETURN(-EINVAL); } - if (copy_from_user(¶m, buffer, sizeof(param))) + if (copy_from_user(¶m, buffer, sizeof(param))) { + CERROR("failed copy data from lgssd\n"); RETURN(-EFAULT); + } if (param.version != GSSD_INTERFACE_VERSION) { CERROR("gssd interface version %d (expect %d)\n", @@ -292,11 +301,6 @@ static int gss_send_secinit_rpc(__user char *buffer, unsigned long count) CERROR("no such obd %s\n", obdname); RETURN(-EINVAL); } - if (strcmp(obd->obd_type->typ_name, "mdc") && - strcmp(obd->obd_type->typ_name, "osc")) { - CERROR("%s not a mdc/osc device\n", obdname); - RETURN(-EINVAL); - } imp = class_import_get(obd->u.cli.cl_import); @@ -311,6 +315,7 @@ static int gss_send_secinit_rpc(__user char *buffer, unsigned long count) /* get token */ reqlen = secinit_compose_request(imp, reqbuf, reqbuf_size, + param.lustre_svc, param.uid, param.gid, param.send_token_size, param.send_token); @@ -319,10 +324,10 @@ static int gss_send_secinit_rpc(__user char *buffer, unsigned long count) goto out_copy; } - replen = repbuf_size; - rc = ptlrpc_do_rawrpc(imp, reqbuf, reqlen, - repbuf, &replen, SECINIT_RPC_TIMEOUT); - if (rc) { + request = ptl_do_rawrpc(imp, reqbuf, reqbuf_size, reqlen, + repbuf, repbuf_size, &replen, + SECINIT_RPC_TIMEOUT, &rc); + if (request == NULL || rc) { param.status = rc; goto out_copy; } @@ -351,32 +356,15 @@ out_copy: rc = 0; class_import_put(imp); - if (repbuf) - OBD_FREE(repbuf, repbuf_size); - if (reqbuf) - OBD_FREE(reqbuf, reqbuf_size); - RETURN(rc); -} - -static int gss_send_secfini_rpc(struct obd_import *imp, - char *reqbuf, int reqlen) -{ - const int repbuf_size = 1024; - char *repbuf; - int replen = repbuf_size; - int rc; - - OBD_ALLOC(repbuf, repbuf_size); - if (!repbuf) { - CERROR("Out of memory\n"); - return -ENOMEM; + if (request == NULL) { + if (repbuf) + OBD_FREE(repbuf, repbuf_size); + if (reqbuf) + OBD_FREE(reqbuf, reqbuf_size); + } else { + rawrpc_req_finished(request); } - - rc = ptlrpc_do_rawrpc(imp, reqbuf, reqlen, repbuf, &replen, - SECFINI_RPC_TIMEOUT); - - OBD_FREE(repbuf, repbuf_size); - return rc; + RETURN(rc); } /********************************************** @@ -511,6 +499,7 @@ static void gss_init_upcall_msg(struct gss_upcall_msg *gmsg, /******************************************** * gss cred manipulation helpers * ********************************************/ +#if 0 static int gss_cred_is_uptodate_ctx(struct ptlrpc_cred *cred) { @@ -525,6 +514,7 @@ int gss_cred_is_uptodate_ctx(struct ptlrpc_cred *cred) read_unlock(&gss_ctx_lock); return res; } +#endif static inline struct gss_cl_ctx * gss_get_ctx(struct gss_cl_ctx *ctx) @@ -587,7 +577,7 @@ void gss_cred_set_ctx(struct ptlrpc_cred *cred, struct gss_cl_ctx *ctx) write_lock(&gss_ctx_lock); old = gcred->gc_ctx; gcred->gc_ctx = ctx; - cred->pc_flags |= PTLRPC_CRED_UPTODATE; + set_bit(PTLRPC_CRED_UPTODATE_BIT, &cred->pc_flags); write_unlock(&gss_ctx_lock); if (old) gss_put_ctx(old); @@ -725,6 +715,8 @@ static int gss_cred_refresh(struct ptlrpc_cred *cred) int res; ENTRY; + might_sleep(); + /* any flags means it has been handled, do nothing */ if (cred->pc_flags & PTLRPC_CRED_FLAGS_MASK) RETURN(0); @@ -746,9 +738,9 @@ static int gss_cred_refresh(struct ptlrpc_cred *cred) obdtype = import->imp_obd->obd_type->typ_name; if (!strcmp(obdtype, "mdc")) - gmd.gum_svc = 0; + gmd.gum_svc = LUSTRE_GSS_SVC_MDS; else if (!strcmp(obdtype, "osc")) - gmd.gum_svc = 1; + gmd.gum_svc = LUSTRE_GSS_SVC_OSS; else { CERROR("gss on %s?\n", obdtype); RETURN(-EINVAL); @@ -785,12 +777,14 @@ again: /* so far we'v created gss_new */ gss_init_upcall_msg(gss_new, gsec, obdname, &gmd); - if (gss_cred_is_uptodate_ctx(cred)) { - /* someone else had done it for us, simply cancel - * our own upcall */ - CDEBUG(D_SEC, "cred("LPU64"/%u) has been refreshed by someone " - "else, simply drop our request\n", - cred->pc_pag, cred->pc_uid); + /* we'v created upcall msg, nobody else should touch the + * flag of this cred, unless be set as dead/expire by + * administrator via lctl etc. + */ + if (cred->pc_flags & PTLRPC_CRED_FLAGS_MASK) { + CWARN("cred %p("LPU64"/%u) was set flags %lx unexpectedly\n", + cred, cred->pc_pag, cred->pc_uid, cred->pc_flags); + cred->pc_flags |= PTLRPC_CRED_DEAD | PTLRPC_CRED_ERROR; gss_unhash_msg_nolock(gss_new); spin_unlock(&gsec->gs_lock); gss_release_msg(gss_new); @@ -841,12 +835,13 @@ waiting: goto out; if (signal_pending(current)) { - CERROR("cred %p: interrupted upcall\n", cred); + CERROR("%s: cred %p: interrupted upcall\n", + current->comm, cred); cred->pc_flags |= PTLRPC_CRED_DEAD | PTLRPC_CRED_ERROR; res = -EINTR; } else if (res == 0) { CERROR("cred %p: upcall timedout\n", cred); - cred->pc_flags |= PTLRPC_CRED_DEAD; + set_bit(PTLRPC_CRED_DEAD_BIT, &cred->pc_flags); res = -ETIMEDOUT; } else res = 0; @@ -913,7 +908,7 @@ static int gss_cred_refresh(struct ptlrpc_cred *cred) if (rc || gss_err) { CERROR("parse init downcall: rpc %d, gss 0x%x\n", rc, gss_err); if (rc != -ERESTART || gss_err != 0) - cred->pc_flags |= PTLRPC_CRED_ERROR; + set_bit(PTLRPC_CRED_ERROR_BIT, &cred->pc_flags); if (rc == 0) rc = -EPERM; goto err_out; @@ -925,7 +920,7 @@ static int gss_cred_refresh(struct ptlrpc_cred *cred) return 0; err_out: - cred->pc_flags |= PTLRPC_CRED_DEAD; + set_bit(PTLRPC_CRED_DEAD_BIT, &cred->pc_flags); return rc; } #endif @@ -977,10 +972,10 @@ static int gss_cred_sign(struct ptlrpc_cred *cred, spin_unlock(&ctx->gc_seq_lock); *vp++ = cpu_to_le32(PTLRPC_SEC_GSS_VERSION); /* version */ - *vp++ = cpu_to_le32(PTLRPC_SEC_GSS_KRB5I); /* subflavor */ + *vp++ = cpu_to_le32(PTLRPCS_FLVR_KRB5I); /* subflavor */ *vp++ = cpu_to_le32(ctx->gc_proc); /* proc */ *vp++ = cpu_to_le32(seqnum); /* seq */ - *vp++ = cpu_to_le32(PTLRPC_GSS_SVC_INTEGRITY); /* service */ + *vp++ = cpu_to_le32(PTLRPCS_GSS_SVC_INTEGRITY); /* service */ vlen -= 5 * 4; if (rawobj_serialize(&ctx->gc_wire_ctx, &vp, &vlen)) { @@ -999,7 +994,8 @@ static int gss_cred_sign(struct ptlrpc_cred *cred, req->rq_reqbuf, lmsg.data, lmsg.len, mic.data, mic.len); major = kgss_get_mic(ctx->gc_gss_ctx, GSS_C_QOP_DEFAULT, &lmsg, &mic); if (major) { - CERROR("gss compute mic error, major %x\n", major); + CERROR("cred %p: req %p compute mic error, major %x\n", + cred, req, major); rc = -EACCES; goto out; } @@ -1048,10 +1044,10 @@ static int gss_cred_verify(struct ptlrpc_cred *cred, vlen -= 3 * 4; switch (proc) { - case PTLRPC_GSS_PROC_DATA: + case PTLRPCS_GSS_PROC_DATA: seq = le32_to_cpu(*vp++); svc = le32_to_cpu(*vp++); - if (svc != PTLRPC_GSS_SVC_INTEGRITY) { + if (svc != PTLRPCS_GSS_SVC_INTEGRITY) { CERROR("Unknown svc %d\n", svc); RETURN(-EPROTO); } @@ -1076,8 +1072,18 @@ static int gss_cred_verify(struct ptlrpc_cred *cred, major = kgss_verify_mic(ctx->gc_gss_ctx, &lmsg, &mic, NULL); if (major != GSS_S_COMPLETE) { - CERROR("gss verify mic error: major %x\n", major); - GOTO(proc_data_out, rc = -EINVAL); + CERROR("cred %p: req %p verify mic error: major %x\n", + cred, req, major); + + if (major == GSS_S_CREDENTIALS_EXPIRED || + major == GSS_S_CONTEXT_EXPIRED) { + ptlrpcs_cred_expire(cred); + req->rq_ptlrpcs_restart = 1; + rc = 0; + } else + rc = -EINVAL; + + GOTO(proc_data_out, rc); } req->rq_repmsg = (struct lustre_msg *) lmsg.data; @@ -1091,7 +1097,7 @@ static int gss_cred_verify(struct ptlrpc_cred *cred, proc_data_out: gss_put_ctx(ctx); break; - case PTLRPC_GSS_PROC_ERR: + case PTLRPCS_GSS_PROC_ERR: major = le32_to_cpu(*vp++); minor = le32_to_cpu(*vp++); /* server return NO_CONTEXT might be caused by context expire @@ -1110,15 +1116,12 @@ proc_data_out: req, cred, (major == GSS_S_NO_CONTEXT) ? "NO_CONTEXT" : "BAD_SIG"); - ptlrpcs_cred_die(cred); - rc = ptlrpcs_req_replace_dead_cred(req); - if (!rc) - req->rq_ptlrpcs_restart = 1; - else - CERROR("replace dead cred failed %d\n", rc); + ptlrpcs_cred_expire(cred); + req->rq_ptlrpcs_restart = 1; + rc = 0; } else { - CERROR("Unrecognized gss error (%x/%x)\n", - major, minor); + CERROR("req %p: unrecognized gss error (%x/%x)\n", + req, major, minor); rc = -EACCES; } break; @@ -1169,10 +1172,10 @@ static int gss_cred_seal(struct ptlrpc_cred *cred, spin_unlock(&ctx->gc_seq_lock); *vp++ = cpu_to_le32(PTLRPC_SEC_GSS_VERSION); /* version */ - *vp++ = cpu_to_le32(PTLRPC_SEC_GSS_KRB5P); /* subflavor */ + *vp++ = cpu_to_le32(PTLRPCS_FLVR_KRB5P); /* subflavor */ *vp++ = cpu_to_le32(ctx->gc_proc); /* proc */ *vp++ = cpu_to_le32(seqnum); /* seq */ - *vp++ = cpu_to_le32(PTLRPC_GSS_SVC_PRIVACY); /* service */ + *vp++ = cpu_to_le32(PTLRPCS_GSS_SVC_PRIVACY); /* service */ vlen -= 5 * 4; if (rawobj_serialize(&ctx->gc_wire_ctx, &vp, &vlen)) { @@ -1185,7 +1188,8 @@ static int gss_cred_seal(struct ptlrpc_cred *cred, vlen -= 4; msg_buf.buf = (__u8 *) req->rq_reqmsg - GSS_PRIVBUF_PREFIX_LEN; - msg_buf.buflen = req->rq_reqlen + GSS_PRIVBUF_PREFIX_LEN + GSS_PRIVBUF_SUFFIX_LEN; + msg_buf.buflen = req->rq_reqlen + GSS_PRIVBUF_PREFIX_LEN + + GSS_PRIVBUF_SUFFIX_LEN; msg_buf.dataoff = GSS_PRIVBUF_PREFIX_LEN; msg_buf.datalen = req->rq_reqlen; @@ -1195,7 +1199,7 @@ static int gss_cred_seal(struct ptlrpc_cred *cred, major = kgss_wrap(ctx->gc_gss_ctx, GSS_C_QOP_DEFAULT, &msg_buf, &cipher_buf); if (major) { - CERROR("error wrap: major 0x%x\n", major); + CERROR("cred %p: error wrap: major 0x%x\n", cred, major); GOTO(out, rc = -EINVAL); } @@ -1221,7 +1225,7 @@ static int gss_cred_unseal(struct ptlrpc_cred *cred, struct ptlrpcs_wire_hdr *sec_hdr; rawobj_t cipher_text, plain_text; __u32 *vp, vlen, subflavor, proc, seq, svc; - int rc; + __u32 major, rc; ENTRY; LASSERT(req->rq_repbuf); @@ -1252,8 +1256,8 @@ static int gss_cred_unseal(struct ptlrpc_cred *cred, vlen -= 5 * 4; switch (proc) { - case PTLRPC_GSS_PROC_DATA: - if (svc != PTLRPC_GSS_SVC_PRIVACY) { + case PTLRPCS_GSS_PROC_DATA: + if (svc != PTLRPCS_GSS_SVC_PRIVACY) { CERROR("Unknown svc %d\n", svc); RETURN(-EPROTO); } @@ -1279,11 +1283,21 @@ static int gss_cred_unseal(struct ptlrpc_cred *cred, ctx = gss_cred_get_ctx(cred); LASSERT(ctx); - rc = kgss_unwrap(ctx->gc_gss_ctx, GSS_C_QOP_DEFAULT, - &cipher_text, &plain_text); - if (rc) { - CERROR("error unwrap: 0x%x\n", rc); - GOTO(proc_out, rc = -EINVAL); + major = kgss_unwrap(ctx->gc_gss_ctx, GSS_C_QOP_DEFAULT, + &cipher_text, &plain_text); + if (major) { + CERROR("cred %p: error unwrap: major 0x%x\n", + cred, major); + + if (major == GSS_S_CREDENTIALS_EXPIRED || + major == GSS_S_CONTEXT_EXPIRED) { + ptlrpcs_cred_expire(cred); + req->rq_ptlrpcs_restart = 1; + rc = 0; + } else + rc = -EINVAL; + + GOTO(proc_out, rc); } req->rq_repmsg = (struct lustre_msg *) vp; @@ -1309,30 +1323,39 @@ static void destroy_gss_context(struct ptlrpc_cred *cred) struct ptlrpc_request req; struct obd_import *imp; __u32 *vp, lmsg_size; + struct ptlrpc_request *raw_req = NULL; + const int repbuf_len = 256; + char *repbuf; + int replen, rc; ENTRY; - /* cred's refcount is 0, steal one */ - atomic_inc(&cred->pc_refcount); - - gcred = container_of(cred, struct gss_cred, gc_base); - gcred->gc_ctx->gc_proc = PTLRPC_GSS_PROC_DESTROY; imp = cred->pc_sec->ps_import; LASSERT(imp); - if (!(cred->pc_flags & PTLRPC_CRED_UPTODATE)) { - CDEBUG(D_SEC, "Destroy a dead gss cred %p(%u@%s)\n", - gcred, cred->pc_uid, imp->imp_target_uuid.uuid); - atomic_dec(&cred->pc_refcount); + if (test_bit(PTLRPC_CRED_ERROR_BIT, &cred->pc_flags) || + !test_bit(PTLRPC_CRED_UPTODATE_BIT, &cred->pc_flags)) { + CDEBUG(D_SEC, "Destroy dead cred %p(%u@%s)\n", + cred, cred->pc_uid, imp->imp_target_uuid.uuid); EXIT; return; } + might_sleep(); + + /* cred's refcount is 0, steal one */ + atomic_inc(&cred->pc_refcount); + + gcred = container_of(cred, struct gss_cred, gc_base); + gcred->gc_ctx->gc_proc = PTLRPCS_GSS_PROC_DESTROY; + CDEBUG(D_SEC, "client destroy gss cred %p(%u@%s)\n", gcred, cred->pc_uid, imp->imp_target_uuid.uuid); lmsg_size = lustre_msg_size(0, NULL); + req.rq_req_secflvr = cred->pc_sec->ps_flavor; + req.rq_cred = cred; req.rq_reqbuf_len = sizeof(*hdr) + lmsg_size + - ptlrpcs_est_req_payload(cred->pc_sec, lmsg_size); + ptlrpcs_est_req_payload(&req, lmsg_size); OBD_ALLOC(req.rq_reqbuf, req.rq_reqbuf_len); if (!req.rq_reqbuf) { @@ -1344,8 +1367,7 @@ static void destroy_gss_context(struct ptlrpc_cred *cred) /* wire hdr */ hdr = buf_to_sec_hdr(req.rq_reqbuf); - hdr->flavor = cpu_to_le32(PTLRPC_SEC_GSS); - hdr->sectype = cpu_to_le32(PTLRPC_SEC_TYPE_AUTH); + hdr->flavor = cpu_to_le32(PTLRPCS_FLVR_GSS_AUTH); hdr->msg_len = cpu_to_le32(lmsg_size); hdr->sec_len = cpu_to_le32(0); @@ -1375,10 +1397,21 @@ static void destroy_gss_context(struct ptlrpc_cred *cred) } atomic_dec(&cred->pc_refcount); - /* send out */ - gss_send_secfini_rpc(imp, req.rq_reqbuf, req.rq_reqdata_len); + OBD_ALLOC(repbuf, repbuf_len); + if (!repbuf) + goto exit; + + raw_req = ptl_do_rawrpc(imp, req.rq_reqbuf, req.rq_reqbuf_len, + req.rq_reqdata_len, repbuf, repbuf_len, &replen, + SECFINI_RPC_TIMEOUT, &rc); + if (!raw_req) + OBD_FREE(repbuf, repbuf_len); + exit: - OBD_FREE(req.rq_reqbuf, req.rq_reqbuf_len); + if (raw_req == NULL) + OBD_FREE(req.rq_reqbuf, req.rq_reqbuf_len); + else + rawrpc_req_finished(raw_req); EXIT; } @@ -1501,12 +1534,12 @@ gss_pipe_downcall(struct file *filp, const char *src, size_t mlen) } if (err || gss_err) { - cred->pc_flags |= PTLRPC_CRED_DEAD; + set_bit(PTLRPC_CRED_DEAD_BIT, &cred->pc_flags); if (err != -ERESTART || gss_err != 0) - cred->pc_flags |= PTLRPC_CRED_ERROR; + set_bit(PTLRPC_CRED_ERROR_BIT, &cred->pc_flags); CERROR("cred %p: rpc err %d, gss err 0x%x, fatal %d\n", - cred, err, gss_err, - ((cred->pc_flags & PTLRPC_CRED_ERROR) != 0)); + cred, err, gss_err, + (test_bit(PTLRPC_CRED_ERROR_BIT, &cred->pc_flags) != 0)); } else { CDEBUG(D_SEC, "get initial ctx:\n"); gss_cred_set_ctx(cred, ctx); @@ -1601,7 +1634,7 @@ static struct rpc_pipe_ops gss_upcall_ops = { *********************************************/ static -struct ptlrpc_sec* gss_create_sec(ptlrpcs_flavor_t *flavor, +struct ptlrpc_sec* gss_create_sec(__u32 flavor, const char *pipe_dir, void *pipe_data) { @@ -1610,10 +1643,11 @@ struct ptlrpc_sec* gss_create_sec(ptlrpcs_flavor_t *flavor, #ifdef __KERNEL__ char *pos; int pipepath_len; + uid_t save_uid; #endif ENTRY; - LASSERT(flavor->flavor == PTLRPC_SEC_GSS); + LASSERT(SEC_FLAVOR_MAJOR(flavor) == PTLRPCS_FLVR_MAJOR_GSS); OBD_ALLOC(gsec, sizeof(*gsec)); if (!gsec) { @@ -1621,9 +1655,9 @@ struct ptlrpc_sec* gss_create_sec(ptlrpcs_flavor_t *flavor, RETURN(NULL); } - gsec->gs_mech = kgss_subflavor_to_mech(flavor->subflavor); + gsec->gs_mech = kgss_subflavor_to_mech(SEC_FLAVOR_SUB(flavor)); if (!gsec->gs_mech) { - CERROR("subflavor %d not found\n", flavor->subflavor); + CERROR("subflavor 0x%x not found\n", flavor); goto err_free; } @@ -1638,6 +1672,10 @@ struct ptlrpc_sec* gss_create_sec(ptlrpcs_flavor_t *flavor, if (!gsec->gs_pipepath) goto err_mech_put; + /* pipe rpc require root permission */ + save_uid = current->fsuid; + current->fsuid = 0; + sprintf(gsec->gs_pipepath, LUSTRE_PIPEDIR"/%s", pipe_dir); if (IS_ERR(rpc_mkdir(gsec->gs_pipepath, NULL))) { CERROR("can't make pipedir %s\n", gsec->gs_pipepath); @@ -1657,22 +1695,12 @@ struct ptlrpc_sec* gss_create_sec(ptlrpcs_flavor_t *flavor, #endif sec = &gsec->gs_base; - - switch (flavor->subflavor) { - case PTLRPC_SEC_GSS_KRB5I: - sec->ps_sectype = PTLRPC_SEC_TYPE_AUTH; - break; - case PTLRPC_SEC_GSS_KRB5P: - sec->ps_sectype = PTLRPC_SEC_TYPE_PRIV; - break; - default: - LBUG(); - } - sec->ps_expire = GSS_CREDCACHE_EXPIRE; sec->ps_nextgc = get_seconds() + sec->ps_expire; sec->ps_flags = 0; + current->fsuid = save_uid; + CDEBUG(D_SEC, "Create GSS security instance at %p(external %p)\n", gsec, sec); RETURN(sec); @@ -1684,6 +1712,7 @@ err_rmdir: *pos = 0; rpc_rmdir(gsec->gs_pipepath); err_free_path: + current->fsuid = save_uid; OBD_FREE(gsec->gs_pipepath, pipepath_len); err_mech_put: #endif @@ -1741,7 +1770,7 @@ struct ptlrpc_cred * gss_create_cred(struct ptlrpc_sec *sec, atomic_set(&cred->pc_refcount, 0); cred->pc_sec = sec; cred->pc_ops = &gss_credops; - cred->pc_expire = get_seconds() + GSS_CRED_EXPIRE; + cred->pc_expire = 0; cred->pc_flags = 0; cred->pc_pag = vcred->vc_pag; cred->pc_uid = vcred->vc_uid; @@ -1751,12 +1780,14 @@ struct ptlrpc_cred * gss_create_cred(struct ptlrpc_sec *sec, RETURN(cred); } -static int gss_estimate_payload(struct ptlrpc_sec *sec, int msgsize) +static int gss_estimate_payload(struct ptlrpc_sec *sec, + struct ptlrpc_request *req, + int msgsize) { - switch (sec->ps_sectype) { - case PTLRPC_SEC_TYPE_AUTH: + switch (SEC_FLAVOR_SVC(req->rq_req_secflvr)) { + case PTLRPCS_SVC_AUTH: return GSS_MAX_AUTH_PAYLOAD; - case PTLRPC_SEC_TYPE_PRIV: + case PTLRPCS_SVC_PRIV: return size_round16(GSS_MAX_AUTH_PAYLOAD + msgsize + GSS_PRIVBUF_PREFIX_LEN + GSS_PRIVBUF_SUFFIX_LEN); @@ -1777,9 +1808,9 @@ static int gss_alloc_reqbuf(struct ptlrpc_sec *sec, /* In PRIVACY mode, lustre message is always 0 (already encoded into * security payload). */ - privacy = sec->ps_sectype == PTLRPC_SEC_TYPE_PRIV; + privacy = (SEC_FLAVOR_SVC(req->rq_req_secflvr) == PTLRPCS_SVC_PRIV); msg_payload = privacy ? 0 : lmsg_size; - sec_payload = gss_estimate_payload(sec, lmsg_size); + sec_payload = gss_estimate_payload(sec, req, lmsg_size); rc = sec_alloc_reqbuf(sec, req, msg_payload, sec_payload); if (rc) @@ -1813,7 +1844,7 @@ static void gss_free_reqbuf(struct ptlrpc_sec *sec, LASSERT(req->rq_reqmsg); LASSERT(req->rq_reqlen); - privacy = sec->ps_sectype == PTLRPC_SEC_TYPE_PRIV; + privacy = SEC_FLAVOR_SVC(req->rq_req_secflvr) == PTLRPCS_SVC_PRIV; if (privacy) { buf = (char *) req->rq_reqmsg - GSS_PRIVBUF_PREFIX_LEN; LASSERT(buf < req->rq_reqbuf || @@ -1838,9 +1869,9 @@ static struct ptlrpc_secops gss_secops = { static struct ptlrpc_sec_type gss_type = { .pst_owner = THIS_MODULE, - .pst_name = "GSS_SEC", + .pst_name = "sec.gss", .pst_inst = ATOMIC_INIT(0), - .pst_flavor = {PTLRPC_SEC_GSS, 0}, + .pst_flavor = PTLRPCS_FLVR_MAJOR_GSS, .pst_ops = &gss_secops, };