]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
RPCSEC_GSS remove all qop parameters
authorJ. Bruce Fields <bfields@fieldses.org>
Thu, 13 Oct 2005 20:55:18 +0000 (16:55 -0400)
committerTrond Myklebust <Trond.Myklebust@netapp.com>
Wed, 19 Oct 2005 06:19:47 +0000 (23:19 -0700)
 Not only are the qop parameters that are passed around throughout the gssapi
 unused by any currently implemented mechanism, but there appears to be some
 doubt as to whether they will ever be used.  Let's just kill them off for now.

Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
14 files changed:
include/linux/sunrpc/gss_api.h
include/linux/sunrpc/gss_err.h
include/linux/sunrpc/gss_krb5.h
include/linux/sunrpc/gss_spkm3.h
net/sunrpc/auth_gss/auth_gss.c
net/sunrpc/auth_gss/gss_krb5_mech.c
net/sunrpc/auth_gss/gss_krb5_seal.c
net/sunrpc/auth_gss/gss_krb5_unseal.c
net/sunrpc/auth_gss/gss_krb5_wrap.c
net/sunrpc/auth_gss/gss_mech_switch.c
net/sunrpc/auth_gss/gss_spkm3_mech.c
net/sunrpc/auth_gss/gss_spkm3_seal.c
net/sunrpc/auth_gss/gss_spkm3_unseal.c
net/sunrpc/auth_gss/svcauth_gss.c

index e896752ffbf9ec629d301538438e71a964f8b2c3..9b8bcf125c18e79332d9c13762dacb85d8eec8b7 100644 (file)
@@ -40,23 +40,19 @@ int gss_import_sec_context(
                struct gss_ctx          **ctx_id);
 u32 gss_get_mic(
                struct gss_ctx          *ctx_id,
-               u32                     qop,
                struct xdr_buf          *message,
                struct xdr_netobj       *mic_token);
 u32 gss_verify_mic(
                struct gss_ctx          *ctx_id,
                struct xdr_buf          *message,
-               struct xdr_netobj       *mic_token,
-               u32                     *qstate);
+               struct xdr_netobj       *mic_token);
 u32 gss_wrap(
                struct gss_ctx          *ctx_id,
-               u32                     qop,
                int                     offset,
                struct xdr_buf          *outbuf,
                struct page             **inpages);
 u32 gss_unwrap(
                struct gss_ctx          *ctx_id,
-               u32                     *qop,
                int                     offset,
                struct xdr_buf          *inbuf);
 u32 gss_delete_sec_context(
@@ -67,7 +63,6 @@ char *gss_service_to_auth_domain_name(struct gss_api_mech *, u32 service);
 
 struct pf_desc {
        u32     pseudoflavor;
-       u32     qop;
        u32     service;
        char    *name;
        char    *auth_domain_name;
@@ -96,23 +91,19 @@ struct gss_api_ops {
                        struct gss_ctx          *ctx_id);
        u32 (*gss_get_mic)(
                        struct gss_ctx          *ctx_id,
-                       u32                     qop, 
                        struct xdr_buf          *message,
                        struct xdr_netobj       *mic_token);
        u32 (*gss_verify_mic)(
                        struct gss_ctx          *ctx_id,
                        struct xdr_buf          *message,
-                       struct xdr_netobj       *mic_token,
-                       u32                     *qstate);
+                       struct xdr_netobj       *mic_token);
        u32 (*gss_wrap)(
                        struct gss_ctx          *ctx_id,
-                       u32                     qop,
                        int                     offset,
                        struct xdr_buf          *outbuf,
                        struct page             **inpages);
        u32 (*gss_unwrap)(
                        struct gss_ctx          *ctx_id,
-                       u32                     *qop,
                        int                     offset,
                        struct xdr_buf          *buf);
        void (*gss_delete_sec_context)(
index 92608a2e574c88b8f548d537f6343f64c52b4766..a6807867bd2105e93af78841e4bb5e8796c2d198 100644 (file)
@@ -65,16 +65,6 @@ typedef unsigned int OM_uint32;
 #define GSS_C_MECH_CODE 2
 
 
-/*
- * Define the default Quality of Protection for per-message services.  Note
- * that an implementation that offers multiple levels of QOP may either reserve
- * a value (for example zero, as assumed here) to mean "default protection", or
- * alternatively may simply equate GSS_C_QOP_DEFAULT to a specific explicit
- * QOP value.  However a value of 0 should always be interpreted by a GSSAPI
- * implementation as a request for the default protection level.
- */
-#define GSS_C_QOP_DEFAULT 0
-
 /*
  * Expiration time of 2^32-1 seconds means infinite lifetime for a
  * credential or security context
index 7f93c2d5ebdb2d2e1ff372056dc754508baa8b2e..a7bda4edb853b55e09fd4dde325cab735b5acc12 100644 (file)
@@ -119,21 +119,21 @@ make_checksum(s32 cksumtype, char *header, int hdrlen, struct xdr_buf *body,
                   int body_offset, struct xdr_netobj *cksum);
 
 u32
-krb5_make_token(struct krb5_ctx *context_handle, int qop_req,
+krb5_make_token(struct krb5_ctx *context_handle,
        struct xdr_buf *input_message_buffer,
        struct xdr_netobj *output_message_buffer);
 
 u32
 krb5_read_token(struct krb5_ctx *context_handle,
          struct xdr_netobj *input_token_buffer,
-         struct xdr_buf *message_buffer, int *qop_state);
+         struct xdr_buf *message_buffer);
 
 u32
-gss_wrap_kerberos(struct gss_ctx *ctx_id, u32 qop, int offset,
+gss_wrap_kerberos(struct gss_ctx *ctx_id, int offset,
                struct xdr_buf *outbuf, struct page **pages);
 
 u32
-gss_unwrap_kerberos(struct gss_ctx *ctx_id, u32 *qop, int offset,
+gss_unwrap_kerberos(struct gss_ctx *ctx_id, int offset,
                struct xdr_buf *buf);
 
 
index b5c9968c3c171b55223f3806fc03dbaf49a7fb64..0beb2cf00a8401b55bd6bad5430cb85960815cb1 100644 (file)
@@ -41,9 +41,9 @@ struct spkm3_ctx {
 #define SPKM_WRAP_TOK  5
 #define SPKM_DEL_TOK   6
 
-u32 spkm3_make_token(struct spkm3_ctx *ctx, int qop_req, struct xdr_buf * text, struct xdr_netobj * token, int toktype);
+u32 spkm3_make_token(struct spkm3_ctx *ctx, struct xdr_buf * text, struct xdr_netobj * token, int toktype);
 
-u32 spkm3_read_token(struct spkm3_ctx *ctx, struct xdr_netobj *read_token, struct xdr_buf *message_buffer, int *qop_state, int toktype);
+u32 spkm3_read_token(struct spkm3_ctx *ctx, struct xdr_netobj *read_token, struct xdr_buf *message_buffer, int toktype);
 
 #define CKSUMTYPE_RSA_MD5            0x0007
 
index 5e4872058ec7cc8bdae8dc54a75fe67f1239c900..f44f46f1d8e053c0d330b442c2f3788cf4073dd4 100644 (file)
@@ -854,9 +854,7 @@ gss_marshal(struct rpc_task *task, u32 *p)
        *p++ = htonl(RPC_AUTH_GSS);
 
        mic.data = (u8 *)(p + 1);
-       maj_stat = gss_get_mic(ctx->gc_gss_ctx,
-                              GSS_C_QOP_DEFAULT, 
-                              &verf_buf, &mic);
+       maj_stat = gss_get_mic(ctx->gc_gss_ctx, &verf_buf, &mic);
        if (maj_stat == GSS_S_CONTEXT_EXPIRED) {
                cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
        } else if (maj_stat != 0) {
@@ -888,7 +886,7 @@ gss_validate(struct rpc_task *task, u32 *p)
 {
        struct rpc_cred *cred = task->tk_msg.rpc_cred;
        struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred);
-       u32             seq, qop_state;
+       u32             seq;
        struct kvec     iov;
        struct xdr_buf  verf_buf;
        struct xdr_netobj mic;
@@ -909,7 +907,7 @@ gss_validate(struct rpc_task *task, u32 *p)
        mic.data = (u8 *)p;
        mic.len = len;
 
-       maj_stat = gss_verify_mic(ctx->gc_gss_ctx, &verf_buf, &mic, &qop_state);
+       maj_stat = gss_verify_mic(ctx->gc_gss_ctx, &verf_buf, &mic);
        if (maj_stat == GSS_S_CONTEXT_EXPIRED)
                cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
        if (maj_stat)
@@ -961,8 +959,7 @@ gss_wrap_req_integ(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
        p = iov->iov_base + iov->iov_len;
        mic.data = (u8 *)(p + 1);
 
-       maj_stat = gss_get_mic(ctx->gc_gss_ctx,
-                       GSS_C_QOP_DEFAULT, &integ_buf, &mic);
+       maj_stat = gss_get_mic(ctx->gc_gss_ctx, &integ_buf, &mic);
        status = -EIO; /* XXX? */
        if (maj_stat == GSS_S_CONTEXT_EXPIRED)
                cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
@@ -1057,8 +1054,7 @@ gss_wrap_req_priv(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
                memcpy(tmp, snd_buf->tail[0].iov_base, snd_buf->tail[0].iov_len);
                snd_buf->tail[0].iov_base = tmp;
        }
-       maj_stat = gss_wrap(ctx->gc_gss_ctx, GSS_C_QOP_DEFAULT, offset,
-                               snd_buf, inpages);
+       maj_stat = gss_wrap(ctx->gc_gss_ctx, offset, snd_buf, inpages);
        /* RPC_SLACK_SPACE should prevent this ever happening: */
        BUG_ON(snd_buf->len > snd_buf->buflen);
         status = -EIO;
@@ -1150,8 +1146,7 @@ gss_unwrap_resp_integ(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
        if (xdr_buf_read_netobj(rcv_buf, &mic, mic_offset))
                return status;
 
-       maj_stat = gss_verify_mic(ctx->gc_gss_ctx, &integ_buf,
-                       &mic, NULL);
+       maj_stat = gss_verify_mic(ctx->gc_gss_ctx, &integ_buf, &mic);
        if (maj_stat == GSS_S_CONTEXT_EXPIRED)
                cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
        if (maj_stat != GSS_S_COMPLETE)
@@ -1176,8 +1171,7 @@ gss_unwrap_resp_priv(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
        /* remove padding: */
        rcv_buf->len = offset + opaque_len;
 
-       maj_stat = gss_unwrap(ctx->gc_gss_ctx, NULL,
-                       offset, rcv_buf);
+       maj_stat = gss_unwrap(ctx->gc_gss_ctx, offset, rcv_buf);
        if (maj_stat == GSS_S_CONTEXT_EXPIRED)
                cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
        if (maj_stat != GSS_S_COMPLETE)
index 37a9ad97ccd44e9e6eb8c5ffb8302be7f6e3fc9f..9ffac2c50b94db8ef3f391ac41250c1e71e7ec38 100644 (file)
@@ -193,15 +193,12 @@ gss_delete_sec_context_kerberos(void *internal_ctx) {
 static u32
 gss_verify_mic_kerberos(struct gss_ctx         *ctx,
                        struct xdr_buf          *message,
-                       struct xdr_netobj       *mic_token,
-                       u32                     *qstate) {
+                       struct xdr_netobj       *mic_token)
+{
        u32 maj_stat = 0;
-       int qop_state;
        struct krb5_ctx *kctx = ctx->internal_ctx_id;
 
-       maj_stat = krb5_read_token(kctx, mic_token, message, &qop_state);
-       if (!maj_stat && qop_state)
-           *qstate = qop_state;
+       maj_stat = krb5_read_token(kctx, mic_token, message);
 
        dprintk("RPC:      gss_verify_mic_kerberos returning %d\n", maj_stat);
        return maj_stat;
@@ -209,13 +206,12 @@ gss_verify_mic_kerberos(struct gss_ctx            *ctx,
 
 static u32
 gss_get_mic_kerberos(struct gss_ctx    *ctx,
-                    u32                qop,
                     struct xdr_buf     *message,
                     struct xdr_netobj  *mic_token) {
        u32 err = 0;
        struct krb5_ctx *kctx = ctx->internal_ctx_id;
 
-       err = krb5_make_token(kctx, qop, message, mic_token);
+       err = krb5_make_token(kctx, message, mic_token);
 
        dprintk("RPC:      gss_get_mic_kerberos returning %d\n",err);
 
index fb852d9ab06ff290e73c3fffbd88a9597c459cc1..15227c727c8be7927bffef730a17bc14dc6e60c9 100644 (file)
@@ -71,7 +71,7 @@
 #endif
 
 u32
-krb5_make_token(struct krb5_ctx *ctx, int qop_req,
+krb5_make_token(struct krb5_ctx *ctx,
                   struct xdr_buf *text, struct xdr_netobj *token)
 {
        s32                     checksum_type;
@@ -83,9 +83,6 @@ krb5_make_token(struct krb5_ctx *ctx, int qop_req,
 
        now = get_seconds();
 
-       if (qop_req != 0)
-               goto out_err;
-
        switch (ctx->signalg) {
                case SGN_ALG_DES_MAC_MD5:
                        checksum_type = CKSUMTYPE_RSA_MD5;
index c3d6d1bc100caa4ae3e1255d1c961734e8da2e43..bcf978627a7169f40eb32ebfca8cb7235dbd4fdd 100644 (file)
@@ -74,7 +74,7 @@
 u32
 krb5_read_token(struct krb5_ctx *ctx,
                struct xdr_netobj *read_token,
-               struct xdr_buf *message_buffer, int *qop_state)
+               struct xdr_buf *message_buffer)
 {
        int                     signalg;
        int                     sealalg;
@@ -157,9 +157,6 @@ krb5_read_token(struct krb5_ctx *ctx,
 
        /* it got through unscathed.  Make sure the context is unexpired */
 
-       if (qop_state)
-               *qop_state = GSS_C_QOP_DEFAULT;
-
        now = get_seconds();
 
        ret = GSS_S_CONTEXT_EXPIRED;
index ddcde6e42b2315512f29242a7db3b44e372f45a4..af777cf9f2510f7a3780cfcfac6375b21ea61688 100644 (file)
@@ -116,7 +116,7 @@ make_confounder(char *p, int blocksize)
 /* XXX factor out common code with seal/unseal. */
 
 u32
-gss_wrap_kerberos(struct gss_ctx *ctx, u32 qop, int offset,
+gss_wrap_kerberos(struct gss_ctx *ctx, int offset,
                struct xdr_buf *buf, struct page **pages)
 {
        struct krb5_ctx         *kctx = ctx->internal_ctx_id;
@@ -132,9 +132,6 @@ gss_wrap_kerberos(struct gss_ctx *ctx, u32 qop, int offset,
 
        now = get_seconds();
 
-       if (qop != 0)
-               goto out_err;
-
        switch (kctx->signalg) {
                case SGN_ALG_DES_MAC_MD5:
                        checksum_type = CKSUMTYPE_RSA_MD5;
@@ -229,8 +226,7 @@ out_err:
 }
 
 u32
-gss_unwrap_kerberos(struct gss_ctx *ctx, u32 *qop, int offset,
-                       struct xdr_buf *buf)
+gss_unwrap_kerberos(struct gss_ctx *ctx, int offset, struct xdr_buf *buf)
 {
        struct krb5_ctx         *kctx = ctx->internal_ctx_id;
        int                     signalg;
@@ -328,9 +324,6 @@ gss_unwrap_kerberos(struct gss_ctx *ctx, u32 *qop, int offset,
 
        /* it got through unscathed.  Make sure the context is unexpired */
 
-       if (qop)
-               *qop = GSS_C_QOP_DEFAULT;
-
        now = get_seconds();
 
        ret = GSS_S_CONTEXT_EXPIRED;
index 06d97cb3481a3ecf02b82a92d466453c65303a14..b048bf672da2bbffbe35953b3e47a57b7e2383d3 100644 (file)
@@ -250,13 +250,11 @@ gss_import_sec_context(const void *input_token, size_t bufsize,
 
 u32
 gss_get_mic(struct gss_ctx     *context_handle,
-           u32                 qop,
            struct xdr_buf      *message,
            struct xdr_netobj   *mic_token)
 {
         return context_handle->mech_type->gm_ops
                ->gss_get_mic(context_handle,
-                             qop,
                              message,
                              mic_token);
 }
@@ -266,35 +264,31 @@ gss_get_mic(struct gss_ctx        *context_handle,
 u32
 gss_verify_mic(struct gss_ctx          *context_handle,
               struct xdr_buf           *message,
-              struct xdr_netobj        *mic_token,
-              u32                      *qstate)
+              struct xdr_netobj        *mic_token)
 {
        return context_handle->mech_type->gm_ops
                ->gss_verify_mic(context_handle,
                                 message,
-                                mic_token,
-                                qstate);
+                                mic_token);
 }
 
 u32
 gss_wrap(struct gss_ctx        *ctx_id,
-        u32            qop,
         int            offset,
         struct xdr_buf *buf,
         struct page    **inpages)
 {
        return ctx_id->mech_type->gm_ops
-               ->gss_wrap(ctx_id, qop, offset, buf, inpages);
+               ->gss_wrap(ctx_id, offset, buf, inpages);
 }
 
 u32
 gss_unwrap(struct gss_ctx      *ctx_id,
-          u32                  *qop,
           int                  offset,
           struct xdr_buf       *buf)
 {
        return ctx_id->mech_type->gm_ops
-               ->gss_unwrap(ctx_id, qop, offset, buf);
+               ->gss_unwrap(ctx_id, offset, buf);
 }
 
 
index 6c97d61baa9bfa3a819fa079a132eb745babd081..39b3edc146947a9c9918b3a6cbf8c0da9308dec8 100644 (file)
@@ -224,18 +224,13 @@ gss_delete_sec_context_spkm3(void *internal_ctx) {
 static u32
 gss_verify_mic_spkm3(struct gss_ctx            *ctx,
                        struct xdr_buf          *signbuf,
-                       struct xdr_netobj       *checksum,
-                       u32             *qstate) {
+                       struct xdr_netobj       *checksum)
+{
        u32 maj_stat = 0;
-       int qop_state = 0;
        struct spkm3_ctx *sctx = ctx->internal_ctx_id;
 
        dprintk("RPC: gss_verify_mic_spkm3 calling spkm3_read_token\n");
-       maj_stat = spkm3_read_token(sctx, checksum, signbuf, &qop_state,
-                                  SPKM_MIC_TOK);
-
-       if (!maj_stat && qop_state)
-           *qstate = qop_state;
+       maj_stat = spkm3_read_token(sctx, checksum, signbuf, SPKM_MIC_TOK);
 
        dprintk("RPC: gss_verify_mic_spkm3 returning %d\n", maj_stat);
        return maj_stat;
@@ -243,15 +238,15 @@ gss_verify_mic_spkm3(struct gss_ctx               *ctx,
 
 static u32
 gss_get_mic_spkm3(struct gss_ctx       *ctx,
-                    u32                qop,
                     struct xdr_buf     *message_buffer,
-                    struct xdr_netobj  *message_token) {
+                    struct xdr_netobj  *message_token)
+{
        u32 err = 0;
        struct spkm3_ctx *sctx = ctx->internal_ctx_id;
 
        dprintk("RPC: gss_get_mic_spkm3\n");
 
-       err = spkm3_make_token(sctx, qop, message_buffer,
+       err = spkm3_make_token(sctx, message_buffer,
                              message_token, SPKM_MIC_TOK);
        return err;
 }
@@ -264,8 +259,8 @@ static struct gss_api_ops gss_spkm3_ops = {
 };
 
 static struct pf_desc gss_spkm3_pfs[] = {
-       {RPC_AUTH_GSS_SPKM, 0, RPC_GSS_SVC_NONE, "spkm3"},
-       {RPC_AUTH_GSS_SPKMI, 0, RPC_GSS_SVC_INTEGRITY, "spkm3i"},
+       {RPC_AUTH_GSS_SPKM, RPC_GSS_SVC_NONE, "spkm3"},
+       {RPC_AUTH_GSS_SPKMI, RPC_GSS_SVC_INTEGRITY, "spkm3i"},
 };
 
 static struct gss_api_mech gss_spkm3_mech = {
index 25339868d4621bbccdaedc95a3647b3d9843b08d..148201e929d08de77ca44f6b6dfbe8da20ab7e04 100644 (file)
@@ -51,7 +51,7 @@
  */
 
 u32
-spkm3_make_token(struct spkm3_ctx *ctx, int qop_req,
+spkm3_make_token(struct spkm3_ctx *ctx,
                   struct xdr_buf * text, struct xdr_netobj * token,
                   int toktype)
 {
@@ -68,8 +68,6 @@ spkm3_make_token(struct spkm3_ctx *ctx, int qop_req,
        dprintk("RPC: spkm3_make_token\n");
 
        now = jiffies;
-       if (qop_req != 0)
-               goto out_err;
 
        if (ctx->ctx_id.len != 16) {
                dprintk("RPC: spkm3_make_token BAD ctx_id.len %d\n",
index 65ce81bf0bc45789d1bbda9d2d944c41ca6a95c8..c3c0d95861039958305e89f437174b8c3bc13272 100644 (file)
@@ -52,7 +52,7 @@ u32
 spkm3_read_token(struct spkm3_ctx *ctx,
                struct xdr_netobj *read_token,    /* checksum */
                struct xdr_buf *message_buffer, /* signbuf */
-               int *qop_state, int toktype)
+               int toktype)
 {
        s32                     code;
        struct xdr_netobj       wire_cksum = {.len =0, .data = NULL};
index e3308195374e635b2ea617d64fc48684c24d1241..e4ada15ed856feba1f8c26683969c56cac1958b7 100644 (file)
@@ -566,8 +566,7 @@ gss_verify_header(struct svc_rqst *rqstp, struct rsc *rsci,
 
        if (rqstp->rq_deferred) /* skip verification of revisited request */
                return SVC_OK;
-       if (gss_verify_mic(ctx_id, &rpchdr, &checksum, NULL)
-                                                       != GSS_S_COMPLETE) {
+       if (gss_verify_mic(ctx_id, &rpchdr, &checksum) != GSS_S_COMPLETE) {
                *authp = rpcsec_gsserr_credproblem;
                return SVC_DENIED;
        }
@@ -604,7 +603,7 @@ gss_write_verf(struct svc_rqst *rqstp, struct gss_ctx *ctx_id, u32 seq)
        xdr_buf_from_iov(&iov, &verf_data);
        p = rqstp->rq_res.head->iov_base + rqstp->rq_res.head->iov_len;
        mic.data = (u8 *)(p + 1);
-       maj_stat = gss_get_mic(ctx_id, 0, &verf_data, &mic);
+       maj_stat = gss_get_mic(ctx_id, &verf_data, &mic);
        if (maj_stat != GSS_S_COMPLETE)
                return -1;
        *p++ = htonl(mic.len);
@@ -710,7 +709,7 @@ unwrap_integ_data(struct xdr_buf *buf, u32 seq, struct gss_ctx *ctx)
                goto out;
        if (read_bytes_from_xdr_buf(buf, integ_len + 4, mic.data, mic.len))
                goto out;
-       maj_stat = gss_verify_mic(ctx, &integ_buf, &mic, NULL);
+       maj_stat = gss_verify_mic(ctx, &integ_buf, &mic);
        if (maj_stat != GSS_S_COMPLETE)
                goto out;
        if (ntohl(svc_getu32(&buf->head[0])) != seq)
@@ -1012,7 +1011,7 @@ svcauth_gss_release(struct svc_rqst *rqstp)
                        resv = &resbuf->tail[0];
                }
                mic.data = (u8 *)resv->iov_base + resv->iov_len + 4;
-               if (gss_get_mic(gsd->rsci->mechctx, 0, &integ_buf, &mic))
+               if (gss_get_mic(gsd->rsci->mechctx, &integ_buf, &mic))
                        goto out_err;
                svc_putu32(resv, htonl(mic.len));
                memset(mic.data + mic.len, 0,