diff --git a/daemon/nfs41_ops.c b/daemon/nfs41_ops.c index b3dc99b..a83e4de 100644 --- a/daemon/nfs41_ops.c +++ b/daemon/nfs41_ops.c @@ -1623,6 +1623,83 @@ out: return status; } +int nfs41_secinfo( + IN nfs41_session *session, + IN nfs41_path_fh *file, + IN const nfs41_component *name, + OUT nfs41_secinfo_info *secinfo) +{ + int status; + nfs41_compound compound; + nfs_argop4 argops[3]; + nfs_resop4 resops[3]; + nfs41_sequence_args sequence_args; + nfs41_sequence_res sequence_res; + nfs41_putfh_args putfh_args; + nfs41_putfh_res putfh_res; + nfs41_secinfo_args secinfo_args; + nfs41_secinfo_noname_res secinfo_res; + + compound_init(&compound, argops, resops, "secinfo"); + + compound_add_op(&compound, OP_SEQUENCE, &sequence_args, &sequence_res); + status = nfs41_session_sequence(&sequence_args, session, 0); + if (status) + goto out; + + compound_add_op(&compound, OP_PUTFH, &putfh_args, &putfh_res); + putfh_args.file = file; + putfh_args.in_recovery = 0; + + compound_add_op(&compound, OP_SECINFO, &secinfo_args, &secinfo_res); + secinfo_args.name = name; + secinfo_res.secinfo = secinfo; + + status = compound_encode_send_decode(session, &compound, TRUE); + if (status) + goto out; + + compound_error(status = compound.res.status); +out: + return status; +} + +int nfs41_secinfo_noname( + IN nfs41_session *session, + OUT nfs41_secinfo_info *secinfo) +{ + int status; + nfs41_compound compound; + nfs_argop4 argops[3]; + nfs_resop4 resops[3]; + nfs41_sequence_args sequence_args; + nfs41_sequence_res sequence_res; + nfs41_putfh_res putfh_res; + nfs41_secinfo_noname_args noname_args; + nfs41_secinfo_noname_res noname_res; + + compound_init(&compound, argops, resops, "secinfo_no_name"); + + compound_add_op(&compound, OP_SEQUENCE, &sequence_args, &sequence_res); + status = nfs41_session_sequence(&sequence_args, session, 0); + if (status) + goto out; + + compound_add_op(&compound, OP_PUTROOTFH, NULL, &putfh_res); + + compound_add_op(&compound, OP_SECINFO_NO_NAME, &noname_args, &noname_res); + noname_args.type = SECINFO_STYLE4_CURRENT_FH; + noname_res.secinfo = secinfo; + + status = compound_encode_send_decode(session, &compound, TRUE); + if (status) + goto out; + + compound_error(status = compound.res.status); +out: + return status; +} + enum nfsstat4 pnfs_rpc_layoutget( IN nfs41_session *session, IN nfs41_path_fh *file, diff --git a/daemon/nfs41_ops.h b/daemon/nfs41_ops.h index 0c6922f..7936cc1 100644 --- a/daemon/nfs41_ops.h +++ b/daemon/nfs41_ops.h @@ -793,6 +793,45 @@ typedef struct __nfs41_write_res { nfs41_write_res_ok resok4; } nfs41_write_res; +/* OP_SECINFO */ +enum sec_flavor { + RPC_GSS_SVC_NONE = 1, + RPC_GSS_SVC_INTEGRITY = 2, + RPC_GSS_SVC_PRIVACY = 3, +}; + +#define RPCSEC_GSS 6 +#define MAX_OID_LEN 128 +typedef struct __nfs41_secinfo_info { + char oid[MAX_OID_LEN]; + uint32_t oid_len; + uint32_t sec_flavor; + uint32_t qop; + enum sec_flavor type; +} nfs41_secinfo_info; + +typedef struct __nfs41_secinfo_args { + const nfs41_component *name; +} nfs41_secinfo_args; + +#define MAX_SECINFOS 6 + +/* OP_SECINFO_NO_NAME */ +enum secinfo_no_name_type { + SECINFO_STYLE4_CURRENT_FH = 0, + SECINFO_STYLE4_PARENT = 1 +}; + +typedef struct __nfs41_secinfo_noname_args { + enum secinfo_noname_type type; +} nfs41_secinfo_noname_args; + +typedef struct __nfs41_secinfo_noname_res { + uint32_t status; + /* case NFS4_OK: */ + nfs41_secinfo_info *secinfo; + uint32_t count; +} nfs41_secinfo_noname_res; /* LAYOUTGET */ typedef struct __pnfs_layoutget_args { @@ -1096,6 +1135,15 @@ enum nfsstat4 nfs41_fs_locations( IN const nfs41_component *name, OUT fs_locations4 *locations); +int nfs41_secinfo( + IN nfs41_session *session, + IN nfs41_path_fh *file, + IN const nfs41_component *name, + OUT nfs41_secinfo_info *secinfo); + +int nfs41_secinfo_noname( + IN nfs41_session *session, + OUT nfs41_secinfo_info *secinfo); enum nfsstat4 pnfs_rpc_layoutget( IN nfs41_session *session, diff --git a/daemon/nfs41_xdr.c b/daemon/nfs41_xdr.c index 454e5ed..d52ba42 100644 --- a/daemon/nfs41_xdr.c +++ b/daemon/nfs41_xdr.c @@ -2663,7 +2663,98 @@ static bool_t decode_op_write( return TRUE; } +/* + * OP_SECINFO_NO_NAME + */ +static bool_t xdr_secinfo( + XDR *xdr, + nfs41_secinfo_info *secinfo) +{ + if (!xdr_u_int32_t(xdr, &secinfo->sec_flavor)) + return FALSE; + if (secinfo->sec_flavor == RPCSEC_GSS) { + char *p = secinfo->oid; + if (!xdr_bytes(xdr, (char **)&p, &secinfo->oid_len, MAX_OID_LEN)) + return FALSE; + if (!xdr_u_int32_t(xdr, &secinfo->qop)) + return FALSE; + if (!xdr_enum(xdr, (enum_t *)&secinfo->type)) + return FALSE; + } + return TRUE; +} +static bool_t encode_op_secinfo_noname( + XDR *xdr, + nfs_argop4 *argop) +{ + nfs41_secinfo_noname_args *args = (nfs41_secinfo_noname_args *)argop->arg; + + if (unexpected_op(argop->op, OP_SECINFO_NO_NAME)) + return FALSE; + + if (!xdr_enum(xdr, (enum_t *)&args->type)) + return FALSE; + + return TRUE; +} + +static bool_t decode_op_secinfo_noname( + XDR *xdr, + nfs_resop4 *resop) +{ + nfs41_secinfo_noname_res *res = (nfs41_secinfo_noname_res *)resop->res; + nfs41_secinfo_info *secinfo = res->secinfo; + if (unexpected_op(resop->op, OP_SECINFO_NO_NAME)) + return FALSE; + + if (!xdr_u_int32_t(xdr, &res->status)) + return FALSE; + + if (res->status == NFS4_OK) + return xdr_array(xdr, (char**)&secinfo, &res->count, + MAX_SECINFOS, sizeof(nfs41_secinfo_info), (xdrproc_t)xdr_secinfo); + + return TRUE; +} + +/* + * OP_SECINFO + */ +static bool_t encode_op_secinfo( + XDR *xdr, + nfs_argop4 *argop) +{ + nfs41_secinfo_args *args = (nfs41_secinfo_args *)argop->arg; + + if (unexpected_op(argop->op, OP_SECINFO)) + return FALSE; + + if (!encode_component(xdr, args->name)) + return FALSE; + + return TRUE; +} + +static bool_t decode_op_secinfo( + XDR *xdr, + nfs_resop4 *resop) +{ + nfs41_secinfo_noname_res *res = (nfs41_secinfo_noname_res *)resop->res; + nfs41_secinfo_info *secinfo = res->secinfo; + + if (unexpected_op(resop->op, OP_SECINFO)) + return FALSE; + + if (!xdr_u_int32_t(xdr, &res->status)) + return FALSE; + + if (res->status == NFS4_OK) + return xdr_array(xdr, (char**)&secinfo, &res->count, + MAX_SECINFOS, sizeof(nfs41_secinfo_info), (xdrproc_t)xdr_secinfo); + + return TRUE; +} /* * OP_GETDEVICEINFO */ @@ -3231,7 +3322,7 @@ static const op_table_entry g_op_table[] = { { NULL, NULL }, /* OP_RENEW = 30 */ { encode_op_restorefh, decode_op_restorefh }, /* OP_RESTOREFH = 31 */ { encode_op_savefh, decode_op_savefh }, /* OP_SAVEFH = 32 */ - { NULL, NULL }, /* OP_SECINFO = 33 */ + { encode_op_secinfo, decode_op_secinfo }, /* OP_SECINFO = 33 */ { encode_op_setattr, decode_op_setattr }, /* OP_SETATTR = 34 */ { NULL, NULL }, /* OP_SETCLIENTID = 35 */ { NULL, NULL }, /* OP_SETCLIENTID_CONFIRM = 36 */ @@ -3250,7 +3341,7 @@ static const op_table_entry g_op_table[] = { { encode_op_layoutcommit, decode_op_layoutcommit }, /* OP_LAYOUTCOMMIT = 49 */ { encode_op_layoutget, decode_op_layoutget }, /* OP_LAYOUTGET = 50 */ { encode_op_layoutreturn, decode_op_layoutreturn }, /* OP_LAYOUTRETURN = 51 */ - { NULL, NULL }, /* OP_SECINFO_NO_NAME = 52 */ + { encode_op_secinfo_noname, decode_op_secinfo_noname }, /* OP_SECINFO_NO_NAME = 52 */ { encode_op_sequence, decode_op_sequence }, /* OP_SEQUENCE = 53 */ { NULL, NULL }, /* OP_SET_SSV = 54 */ { NULL, NULL }, /* OP_TEST_STATEID = 55 */