--- --- linux-2.6.18-rc5-andros/fs/nfs/nfs4xdr.c | 130 ++++++++++++++++++++++++ linux-2.6.18-rc5-andros/include/linux/nfs4.h | 1 linux-2.6.18-rc5-andros/include/linux/nfs_xdr.h | 11 ++ 3 files changed, 142 insertions(+) diff -puN fs/nfs/nfs4xdr.c~nfs-secinfo-xdr fs/nfs/nfs4xdr.c --- linux-2.6.18-rc5/fs/nfs/nfs4xdr.c~nfs-secinfo-xdr 2006-10-11 17:36:53.000000000 -0400 +++ linux-2.6.18-rc5-andros/fs/nfs/nfs4xdr.c 2006-10-11 17:36:53.000000000 -0400 @@ -47,6 +47,7 @@ #include #include #include +#include #include #include #include @@ -92,6 +93,8 @@ static int nfs4_stat_to_errno(int); 3 + 3 + 3 + 2 * nfs4_name_maxsz)) #define nfs4_fattr_maxsz (nfs4_fattr_bitmap_maxsz + \ nfs4_fattr_value_maxsz) +#define gss_oid_maxsz (GSS_OID_MAX_LEN >> 2) +#define nfs4_flav_info_maxsz (1 + gss_oid_maxsz + 1 + 1) #define decode_getattr_maxsz (op_decode_hdr_maxsz + nfs4_fattr_maxsz) #define encode_savefh_maxsz (op_encode_hdr_maxsz) #define decode_savefh_maxsz (op_decode_hdr_maxsz) @@ -137,6 +140,10 @@ static int nfs4_stat_to_errno(int); #define decode_create_maxsz (op_decode_hdr_maxsz + 8) #define encode_delegreturn_maxsz (op_encode_hdr_maxsz + 4) #define decode_delegreturn_maxsz (op_decode_hdr_maxsz) +#define encode_secinfo_maxsz (op_encode_hdr_maxsz + 1 + nfs4_name_maxsz) +#define decode_secinfo_maxsz (op_decode_hdr_maxsz + \ + (1 + nfs4_flav_info_maxsz) * \ + NFS4_SECINFO_MAXFLAVORS) #define NFS4_enc_compound_sz (1024) /* XXX: large enough? */ #define NFS4_dec_compound_sz (1024) /* XXX: large enough? */ #define NFS4_enc_read_sz (compound_encode_hdr_maxsz + \ @@ -420,6 +427,12 @@ static int nfs4_stat_to_errno(int); decode_putfh_maxsz + \ op_decode_hdr_maxsz + \ nfs4_fattr_bitmap_maxsz) +#define NFS4_enc_secinfo_sz (compound_encode_hdr_maxsz + \ + encode_putfh_maxsz + \ + encode_secinfo_maxsz) +#define NFS4_dec_secinfo_sz (compound_decode_hdr_maxsz + \ + decode_putfh_maxsz + \ + decode_secinfo_maxsz) static struct { unsigned int mode; @@ -1212,6 +1225,18 @@ encode_savefh(struct xdr_stream *xdr) return 0; } +static int encode_secinfo(struct xdr_stream *xdr, const struct qstr *name) +{ + uint32_t *p; + + RESERVE_SPACE(8 + name->len); + WRITE32(OP_SECINFO); + WRITE32(name->len); + WRITEMEM(name->name, name->len); + + return 0; +} + static int encode_setattr(struct xdr_stream *xdr, const struct nfs_setattrargs *arg, const struct nfs_server *server) { int status; @@ -1900,6 +1925,25 @@ static int nfs4_xdr_enc_pathconf(struct } /* +* Encode SECINFO request +*/ +static int nfs4_xdr_enc_secinfo(struct rpc_rqst *req, uint32_t *p, const struct nfs4_secinfo_arg *args) +{ + int status; + struct xdr_stream xdr; + struct compound_hdr hdr = { + .nops = 2, + }; + + xdr_init_encode(&xdr, &req->rq_snd_buf, p); + encode_compound_hdr(&xdr, &hdr); + status = encode_putfh(&xdr, args->dir_fh); + if (!status) + status = encode_secinfo(&xdr, args->name); + return status; +} + +/* * a STATFS request */ static int nfs4_xdr_enc_statfs(struct rpc_rqst *req, uint32_t *p, const struct nfs4_statfs_arg *args) @@ -3549,6 +3593,73 @@ decode_savefh(struct xdr_stream *xdr) return decode_op_hdr(xdr, OP_SAVEFH); } +/* Is a printk needed if + * num_flavors is too big, + * flavor is too big, + * oidlen is too big, + * or if we don't support a pseudoflavor? + * + * Only decode (in order) the pseudoflavors supported by the client. + */ +static int decode_secinfo(struct xdr_stream *xdr, struct nfs4_secinfo_res *res) +{ + uint32_t *p; + uint32_t qop; + uint32_t service; + int status; + int i; + rpc_authflavor_t flavor; + int oidlen; + char oiddata[GSS_OID_MAX_LEN]; + + status = decode_op_hdr(xdr, OP_SECINFO); + if (status) + return status; + + READ_BUF(4); + READ32(res->nflavors); + if (res->nflavors > NFS4_SECINFO_MAXFLAVORS) + res->nflavors = NFS4_SECINFO_MAXFLAVORS; + + for (i = 0; i < res->nflavors; i++) { + READ_BUF(4); + READ32(flavor); + if (flavor > RPC_AUTH_MAXFLAVOR) + /* XXX -EINVAL ?? */ + continue; + switch (flavor) { + case RPC_AUTH_GSS: + /* oid */ + READ_BUF(4); + READ32(oidlen); + if (oidlen > GSS_OID_MAX_LEN) + /* XXX -EINVAL ?*/ + return -EINVAL; + READ_BUF(oidlen); + COPYMEM(oiddata, oidlen); + + /* qop - ignore for now */ + READ_BUF(4); + READ32(qop); + + /* service */ + READ_BUF(4); + READ32(service); + res->flavors[i] = + gss_triple_to_pseudoflavor(oidlen, + oiddata, service); + break; + case RPC_AUTH_UNIX: + case RPC_AUTH_NULL: + default: + res->flavors[i] = flavor; + break; + } + } + return 0; +} + + static int decode_setattr(struct xdr_stream *xdr, struct nfs_setattrres *res) { uint32_t *p; @@ -4278,6 +4389,24 @@ static int nfs4_xdr_dec_pathconf(struct return status; } + /* + * Decode SECINFO response + */ +static int nfs4_xdr_dec_secinfo(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_secinfo_res *res) +{ + struct xdr_stream xdr; + struct compound_hdr hdr; + int status; + + xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p); + status = decode_compound_hdr(&xdr, &hdr); + if (!status) + status = decode_putfh(&xdr); + if (!status) + status = decode_secinfo(&xdr, res); + return status; +} + /* * STATFS request */ @@ -4589,6 +4718,7 @@ struct rpc_procinfo nfs4_procedures[] = PROC(GETACL, enc_getacl, dec_getacl), PROC(SETACL, enc_setacl, dec_setacl), PROC(FS_LOCATIONS, enc_fs_locations, dec_fs_locations), + PROC(SECINFO, enc_secinfo, dec_secinfo), }; struct rpc_version nfs_version4 = { diff -puN include/linux/nfs4.h~nfs-secinfo-xdr include/linux/nfs4.h --- linux-2.6.18-rc5/include/linux/nfs4.h~nfs-secinfo-xdr 2006-10-11 17:36:53.000000000 -0400 +++ linux-2.6.18-rc5-andros/include/linux/nfs4.h 2006-10-11 17:36:53.000000000 -0400 @@ -391,6 +391,7 @@ enum { NFSPROC4_CLNT_GETACL, NFSPROC4_CLNT_SETACL, NFSPROC4_CLNT_FS_LOCATIONS, + NFSPROC4_CLNT_SECINFO, }; #endif diff -puN include/linux/nfs_xdr.h~nfs-secinfo-xdr include/linux/nfs_xdr.h --- linux-2.6.18-rc5/include/linux/nfs_xdr.h~nfs-secinfo-xdr 2006-10-11 17:36:53.000000000 -0400 +++ linux-2.6.18-rc5-andros/include/linux/nfs_xdr.h 2006-10-11 17:36:53.000000000 -0400 @@ -320,6 +320,17 @@ struct nfs_renameargs { unsigned int tolen; }; +struct nfs4_secinfo_arg { + const struct nfs_fh * dir_fh; + const struct qstr * name; +}; + +#define NFS4_SECINFO_MAXFLAVORS 12 +struct nfs4_secinfo_res { + unsigned int nflavors; + rpc_authflavor_t flavors[NFS4_SECINFO_MAXFLAVORS]; +}; + struct nfs_setattrargs { struct nfs_fh * fh; nfs4_stateid stateid; _