From 98f19977e92a8fae718e6a2d2515ad609e63f952 Mon Sep 17 00:00:00 2001 From: cphillip Date: Tue, 8 Oct 2002 20:07:11 +0000 Subject: [PATCH] o Merge in OPENSSH_3_4P1_GSI_20021008. --- openssh/auth2-gss.c | 22 +++++++----- openssh/gss-genr.c | 29 ++++++++-------- openssh/kexgss.c | 12 ++++--- openssh/monitor.c | 76 ++++++++++++++++++++++++++++++++++++++++++ openssh/monitor.h | 2 ++ openssh/monitor_wrap.c | 66 ++++++++++++++++++++++++++++++++++++ openssh/monitor_wrap.h | 7 ++++ openssh/readconf.c | 10 +++++- openssh/readconf.h | 1 + openssh/ssh_config.5 | 5 +++ openssh/sshconnect2.c | 31 +++++++++-------- 11 files changed, 220 insertions(+), 41 deletions(-) diff --git a/openssh/auth2-gss.c b/openssh/auth2-gss.c index ddaf953..c207961 100644 --- a/openssh/auth2-gss.c +++ b/openssh/auth2-gss.c @@ -142,15 +142,6 @@ input_gssapi_token(int type, u_int32_t plen, void *ctxt) &send_tok, NULL)); packet_check_eom(); - if (GSS_ERROR(maj_status)) { - /* Failure */ - ssh_gssapi_send_error(gssctxt->oid,maj_status,min_status); - authctxt->postponed = 0; - dispatch_set(SSH_MSG_AUTH_GSSAPI_TOKEN, NULL); - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); - userauth_finish(authctxt, 0, "gssapi"); - } - if (send_tok.length != 0) { /* Send a packet back to the client */ if (!compat20) @@ -163,6 +154,19 @@ input_gssapi_token(int type, u_int32_t plen, void *ctxt) gss_release_buffer(&min_status, &send_tok); } + if (GSS_ERROR(maj_status)) { + /* Failure */ + if (gssctxt) { /* may be NULL under privsep */ + ssh_gssapi_send_error(gssctxt->oid,maj_status,min_status); + } else { + ssh_gssapi_send_error(GSS_C_NO_OID,maj_status,min_status); + } + authctxt->postponed = 0; + dispatch_set(SSH_MSG_AUTH_GSSAPI_TOKEN, NULL); + dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); + userauth_finish(authctxt, 0, "gssapi"); + } + if (maj_status == GSS_S_COMPLETE) { dispatch_set(SSH_MSG_AUTH_GSSAPI_TOKEN, NULL); dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN,NULL); diff --git a/openssh/gss-genr.c b/openssh/gss-genr.c index ccd6d7e..334536e 100644 --- a/openssh/gss-genr.c +++ b/openssh/gss-genr.c @@ -110,7 +110,7 @@ ssh_gssapi_mechanisms(int server,char *host) { if (datafellows & SSH_OLD_GSSAPI) return NULL; - gss_indicate_mechs(&min_status, &supported); + PRIVSEP(gss_indicate_mechs(&min_status, &supported)); buffer_init(&buf); @@ -169,7 +169,7 @@ void ssh_gssapi_supported_oids(gss_OID_set *oidset) { gss_OID_set supported; gss_create_empty_oid_set(&min_status,oidset); - gss_indicate_mechs(&min_status, &supported); + PRIVSEP(gss_indicate_mechs(&min_status, &supported)); while (supported_mechs[i].name!=NULL) { if ((maj_status=gss_test_oid_set_member(&min_status, @@ -260,10 +260,10 @@ ssh_gssapi_error_ex(gss_OID mech, OM_uint32 major_status, ctx = 0; /* The GSSAPI error */ do { - lmaj = gss_display_status(&lmin, major_status, - GSS_C_GSS_CODE, - mech, - &ctx, &msg); + lmaj = PRIVSEP(gss_display_status(&lmin, major_status, + GSS_C_GSS_CODE, + mech, + &ctx, &msg)); if (lmaj == GSS_S_COMPLETE) { debug((char *)msg.value); if (send_packet) packet_send_debug((char *)msg.value); @@ -273,10 +273,10 @@ ssh_gssapi_error_ex(gss_OID mech, OM_uint32 major_status, /* The mechanism specific error */ do { - lmaj = gss_display_status(&lmin, minor_status, - GSS_C_MECH_CODE, - mech, - &ctx, &msg); + lmaj = PRIVSEP(gss_display_status(&lmin, minor_status, + GSS_C_MECH_CODE, + mech, + &ctx, &msg)); if (lmaj == GSS_S_COMPLETE) { debug((char *)msg.value); if (send_packet) packet_send_debug((char *)msg.value); @@ -320,7 +320,9 @@ ssh_gssapi_build_ctx(Gssctxt **ctx) void ssh_gssapi_delete_ctx(Gssctxt **ctx) { +#if !defined(MECHGLUE) OM_uint32 ms; +#endif /* Return if there's no context */ if ((*ctx)==NULL) @@ -396,6 +398,7 @@ OM_uint32 ssh_gssapi_accept_ctx(Gssctxt *ctx,gss_buffer_desc *recv_tok, gss_buffer_desc *send_tok, OM_uint32 *flags) { OM_uint32 maj_status, min_status; + gss_OID mech; maj_status=gss_accept_sec_context(&min_status, &ctx->context, @@ -403,7 +406,7 @@ OM_uint32 ssh_gssapi_accept_ctx(Gssctxt *ctx,gss_buffer_desc *recv_tok, recv_tok, GSS_C_NO_CHANNEL_BINDINGS, &ctx->client, - &ctx->oid, + &mech, /* read-only pointer */ send_tok, flags, NULL, @@ -507,7 +510,7 @@ ssh_gssapi_acquire_cred(Gssctxt *ctx) { &ctx->creds, NULL, NULL))) { - ssh_gssapi_error(GSS_C_NO_OID,maj_status,min_status); + ssh_gssapi_error(ctx->oid,maj_status,min_status); } gss_release_oid_set(&min_status, &oidset); @@ -525,7 +528,7 @@ ssh_gssapi_getclient(Gssctxt *ctx, enum ssh_gss_id *type, *type=ssh_gssapi_get_ctype(ctx); if ((maj_status=gss_display_name(&min_status,ctx->client,name,NULL))) { - ssh_gssapi_error(GSS_C_NO_OID,maj_status,min_status); + ssh_gssapi_error(ctx->oid,maj_status,min_status); } /* This is icky. There appears to be no way to copy this structure, diff --git a/openssh/kexgss.c b/openssh/kexgss.c index 7d18b1a..d202a87 100644 --- a/openssh/kexgss.c +++ b/openssh/kexgss.c @@ -371,18 +371,18 @@ kexgss_server(Kex *kex) } while (maj_status & GSS_S_CONTINUE_NEEDED); if (GSS_ERROR(maj_status)) { - ssh_gssapi_send_error(ctxt->oid,maj_status,min_status); + ssh_gssapi_send_error(oid,maj_status,min_status); packet_disconnect("gssapi key exchange handshake failed"); } debug("gss_complete"); if (!(ret_flags & GSS_C_MUTUAL_FLAG)) { - ssh_gssapi_send_error(ctxt->oid,maj_status,min_status); + ssh_gssapi_send_error(oid,maj_status,min_status); packet_disconnect("gssapi mutual authentication failed"); } if (!(ret_flags & GSS_C_INTEG_FLAG)) { - ssh_gssapi_send_error(ctxt->oid,maj_status,min_status); + ssh_gssapi_send_error(oid,maj_status,min_status); packet_disconnect("gssapi channel integrity not established"); } @@ -423,7 +423,11 @@ kexgss_server(Kex *kex) gssbuf.length = 20; /* Hashlen appears to always be 20 */ if (GSS_ERROR(PRIVSEP(ssh_gssapi_sign(ctxt,&gssbuf,&msg_tok)))) { - ssh_gssapi_send_error(ctxt->oid,maj_status,min_status); + if (ctxt) { /* may be NULL under privsep */ + ssh_gssapi_send_error(ctxt->oid,maj_status,min_status); + } else { + ssh_gssapi_send_error(GSS_C_NO_OID,maj_status,min_status); + } packet_disconnect("Couldn't get MIC"); } diff --git a/openssh/monitor.c b/openssh/monitor.c index 582f0ca..38ee51b 100644 --- a/openssh/monitor.c +++ b/openssh/monitor.c @@ -131,6 +131,8 @@ int mm_answer_gss_accept_ctx(int, Buffer *); int mm_answer_gss_userok(int, Buffer *); int mm_answer_gss_localname(int, Buffer *); int mm_answer_gss_sign(int, Buffer *); +int mm_answer_gss_indicate_mechs(int, Buffer *); +int mm_answer_gss_display_status(int, Buffer *); #endif #ifdef GSI @@ -186,6 +188,8 @@ struct mon_table mon_dispatch_proto20[] = { {MONITOR_REQ_GSSSETUP, MON_ISAUTH, mm_answer_gss_setup_ctx}, {MONITOR_REQ_GSSSTEP, MON_ISAUTH, mm_answer_gss_accept_ctx}, {MONITOR_REQ_GSSSIGN, MON_ONCE, mm_answer_gss_sign}, + {MONITOR_REQ_GSSMECHS, MON_ISAUTH, mm_answer_gss_indicate_mechs}, + {MONITOR_REQ_GSSSTAT, MON_ISAUTH, mm_answer_gss_display_status}, {MONITOR_REQ_GSSUSEROK, MON_AUTH, mm_answer_gss_userok}, {MONITOR_REQ_GSSLOCALNAME, MON_AUTH, mm_answer_gss_localname}, #endif @@ -199,6 +203,8 @@ struct mon_table mon_dispatch_postauth20[] = { {MONITOR_REQ_GSSSETUP, 0, mm_answer_gss_setup_ctx}, {MONITOR_REQ_GSSSTEP, 0, mm_answer_gss_accept_ctx}, {MONITOR_REQ_GSSSIGN, 0, mm_answer_gss_sign}, + {MONITOR_REQ_GSSMECHS, 0, mm_answer_gss_indicate_mechs}, + {MONITOR_REQ_GSSSTAT, 0, mm_answer_gss_display_status}, #endif {MONITOR_REQ_MODULI, 0, mm_answer_moduli}, {MONITOR_REQ_SIGN, 0, mm_answer_sign}, @@ -230,6 +236,8 @@ struct mon_table mon_dispatch_proto15[] = { {MONITOR_REQ_GSSSTEP, MON_ISAUTH, mm_answer_gss_accept_ctx}, {MONITOR_REQ_GSSSIGN, MON_ONCE, mm_answer_gss_sign}, {MONITOR_REQ_GSSUSEROK, MON_AUTH, mm_answer_gss_userok}, + {MONITOR_REQ_GSSMECHS, MON_ISAUTH, mm_answer_gss_indicate_mechs}, + {MONITOR_REQ_GSSSTAT, MON_ISAUTH, mm_answer_gss_display_status}, #endif #ifdef GSI {MONITOR_REQ_GSIGRIDMAP, MON_PERMIT, mm_answer_gsi_gridmap}, @@ -245,6 +253,8 @@ struct mon_table mon_dispatch_postauth15[] = { {MONITOR_REQ_GSSSETUP, 0, mm_answer_gss_setup_ctx}, {MONITOR_REQ_GSSSTEP, 0, mm_answer_gss_accept_ctx}, {MONITOR_REQ_GSSSIGN, 0, mm_answer_gss_sign}, + {MONITOR_REQ_GSSMECHS, 0, mm_answer_gss_indicate_mechs}, + {MONITOR_REQ_GSSSTAT, 0, mm_answer_gss_display_status}, #endif {MONITOR_REQ_PTY, MON_ONCE, mm_answer_pty}, {MONITOR_REQ_PTYCLEANUP, MON_ONCE, mm_answer_pty_cleanup}, @@ -302,6 +312,8 @@ monitor_child_preauth(struct monitor *pmonitor) monitor_permit(mon_dispatch, MONITOR_REQ_GSSSETUP, 1); monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP, 1); monitor_permit(mon_dispatch, MONITOR_REQ_GSSSIGN, 1); + monitor_permit(mon_dispatch, MONITOR_REQ_GSSMECHS, 1); + monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTAT, 1); #endif } else { mon_dispatch = mon_dispatch_proto15; @@ -309,6 +321,8 @@ monitor_child_preauth(struct monitor *pmonitor) monitor_permit(mon_dispatch, MONITOR_REQ_SESSKEY, 1); #ifdef GSSAPI monitor_permit(mon_dispatch, MONITOR_REQ_GSSSIGN, 1); + monitor_permit(mon_dispatch, MONITOR_REQ_GSSMECHS, 1); + monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTAT, 1); #endif #ifdef GSI monitor_permit(mon_dispatch, MONITOR_REQ_GSIGRIDMAP, 1); @@ -367,6 +381,9 @@ monitor_child_postauth(struct monitor *pmonitor) mon_dispatch = mon_dispatch_postauth15; monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1); } +#ifdef GSSAPI + monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTAT, 1); +#endif if (!no_pty_flag) { monitor_permit(mon_dispatch, MONITOR_REQ_PTY, 1); monitor_permit(mon_dispatch, MONITOR_REQ_PTYCLEANUP, 1); @@ -1710,6 +1727,65 @@ mm_answer_gss_sign(int socket, Buffer *m) { return(0); } +int +mm_answer_gss_indicate_mechs(int socket, Buffer *m) { + OM_uint32 major,minor; + gss_OID_set mech_set; + int i; + + major=gss_indicate_mechs(&minor, &mech_set); + + buffer_clear(m); + buffer_put_int(m, major); + buffer_put_int(m, mech_set->count); + for (i=0; i < mech_set->count; i++) { + buffer_put_string(m, mech_set->elements[i].elements, + mech_set->elements[i].length); + } + + mm_request_send(socket,MONITOR_ANS_GSSMECHS,m); + + return(0); +} + +int +mm_answer_gss_display_status(int socket, Buffer *m) { + OM_uint32 major,minor,status_value,message_context; + int status_type; + gss_OID_desc mech_type_desc; + gss_OID mech_type; + gss_buffer_desc status_string; + u_int length; + + status_value = buffer_get_int(m); + status_type = buffer_get_int(m); + mech_type_desc.elements = buffer_get_string(m, &length); + mech_type_desc.length = length; + if (length != 0) { + mech_type = &mech_type_desc; + } else if (gsscontext) { + mech_type = gsscontext->oid; + } else { + mech_type = GSS_C_NO_OID; + } + message_context = buffer_get_int(m); + + major=gss_display_status(&minor, status_value, status_type, mech_type, + &message_context, &status_string); + + buffer_clear(m); + buffer_put_int(m, message_context); + buffer_put_string(m, status_string.value, status_string.length); + + mm_request_send(socket,MONITOR_ANS_GSSSTAT,m); + + if (mech_type_desc.elements) { + xfree(mech_type_desc.elements); + } + + return 0; +} + #endif /* GSSAPI */ #ifdef GSI diff --git a/openssh/monitor.h b/openssh/monitor.h index c23eea4..83e4986 100644 --- a/openssh/monitor.h +++ b/openssh/monitor.h @@ -42,6 +42,8 @@ enum monitor_reqtype { MONITOR_REQ_GSSSETUP,MONITOR_ANS_GSSSETUP, MONITOR_REQ_GSSSTEP,MONITOR_ANS_GSSSTEP, MONITOR_REQ_GSSSIGN,MONITOR_ANS_GSSSIGN, + MONITOR_REQ_GSSMECHS,MONITOR_ANS_GSSMECHS, + MONITOR_REQ_GSSSTAT,MONITOR_ANS_GSSSTAT, MONITOR_REQ_GSSUSEROK,MONITOR_ANS_GSSUSEROK, MONITOR_REQ_GSSLOCALNAME,MONITOR_ANS_GSSLOCALNAME, MONITOR_REQ_GSIGRIDMAP,MONITOR_ANS_GSIGRIDMAP, diff --git a/openssh/monitor_wrap.c b/openssh/monitor_wrap.c index 2f07edc..099a627 100644 --- a/openssh/monitor_wrap.c +++ b/openssh/monitor_wrap.c @@ -1043,6 +1043,72 @@ mm_ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_desc *data, gss_buffer_desc *hash) { return(major); } + +OM_uint32 +mm_gss_indicate_mechs(OM_uint32 *minor_status, gss_OID_set *mech_set) +{ + Buffer m; + OM_uint32 major; + int i=0; + + buffer_init(&m); + + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSMECHS, &m); + + debug3("%s: waiting for MONITOR_ANS_GSSMECHS",__func__); + mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSMECHS, + &m); + major=buffer_get_int(&m); + *mech_set = xmalloc(sizeof(gss_OID_set_desc)); + (*mech_set)->count=buffer_get_int(&m); + (*mech_set)->elements=xmalloc(sizeof(gss_OID_desc)*(*mech_set)->count); + for (i=0; i < (*mech_set)->count; i++) { + u_int length; + (*mech_set)->elements[i].elements=buffer_get_string(&m, &length); + (*mech_set)->elements[i].length = length; + } + + return(major); +} + +OM_uint32 +mm_gss_display_status(OM_uint32 *minor_status, OM_uint32 status_value, + int status_type, const gss_OID mech_type, + OM_uint32 *message_context, gss_buffer_t status_string) +{ + Buffer m; + OM_uint32 major; + + buffer_init(&m); + + buffer_put_int(&m, status_value); + buffer_put_int(&m, status_type); + if (mech_type) { + buffer_put_string(&m, mech_type->elements, mech_type->length); + } else { + buffer_put_string(&m, "", 0); + } + if (message_context) { + buffer_put_int(&m, *message_context); + } else { + buffer_put_int(&m, 0); + } + + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSTAT, &m); + + debug3("%s: waiting for MONITOR_ANS_GSSMECHS",__func__); + mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSTAT, + &m); + + if (message_context) { + *message_context = buffer_get_int(&m); + } else { + buffer_get_int(&m); + } + status_string->value = buffer_get_string(&m, &status_string->length); + + return major; +} #endif /* GSSAPI */ #ifdef GSI diff --git a/openssh/monitor_wrap.h b/openssh/monitor_wrap.h index cd8a042..04491b4 100644 --- a/openssh/monitor_wrap.h +++ b/openssh/monitor_wrap.h @@ -68,6 +68,13 @@ OM_uint32 mm_ssh_gssapi_sign(Gssctxt *ctxt, gss_buffer_desc *buffer, gss_buffer_desc *hash); int mm_ssh_gssapi_userok(char *user); int mm_ssh_gssapi_localname(char **user); +OM_uint32 mm_gss_indicate_mechs(OM_uint32 *minor_status, + gss_OID_set *mech_set); +OM_uint32 mm_gss_display_status(OM_uint32 *minor_status, + OM_uint32 status_value, + int status_type, const gss_OID mech_type, + OM_uint32 *message_context, + gss_buffer_t status_string); #endif #ifdef GSI diff --git a/openssh/readconf.c b/openssh/readconf.c index 30d4332..211075d 100644 --- a/openssh/readconf.c +++ b/openssh/readconf.c @@ -98,7 +98,7 @@ typedef enum { oKerberosAuthentication, #endif #ifdef GSSAPI - oGssAuthentication, oGssDelegateCreds, + oGssAuthentication, oGssKeyEx, oGssDelegateCreds, #ifdef GSI oGssGlobusDelegateLimitedCreds, #endif /* GSI */ @@ -151,6 +151,7 @@ static struct { #endif #ifdef GSSAPI { "gssapiauthentication", oGssAuthentication }, + { "gssapikeyexchange", oGssKeyEx }, { "gssapidelegatecredentials", oGssDelegateCreds }, #ifdef GSI /* For backwards compatability with old 1.2.27 client code */ @@ -382,6 +383,10 @@ parse_flag: intptr = &options->gss_authentication; goto parse_flag; + case oGssKeyEx: + intptr = &options->gss_keyex; + goto parse_flag; + case oGssDelegateCreds: intptr = &options->gss_deleg_creds; goto parse_flag; @@ -781,6 +786,7 @@ initialize_options(Options * options) options->challenge_response_authentication = -1; #ifdef GSSAPI options->gss_authentication = -1; + options->gss_keyex = -1; options->gss_deleg_creds = -1; #ifdef GSI options->gss_globus_deleg_limited_proxy = -1; @@ -866,6 +872,8 @@ fill_default_options(Options * options) #ifdef GSSAPI if (options->gss_authentication == -1) options->gss_authentication = 1; + if (options->gss_keyex == -1) + options->gss_keyex = 1; if (options->gss_deleg_creds == -1) options->gss_deleg_creds = 1; #ifdef GSI diff --git a/openssh/readconf.h b/openssh/readconf.h index f370adf..74ae2fd 100644 --- a/openssh/readconf.h +++ b/openssh/readconf.h @@ -50,6 +50,7 @@ typedef struct { #ifdef GSSAPI int gss_authentication; + int gss_keyex; int gss_deleg_creds; #ifdef GSI int gss_globus_deleg_limited_proxy; diff --git a/openssh/ssh_config.5 b/openssh/ssh_config.5 index c1796eb..aecc799 100644 --- a/openssh/ssh_config.5 +++ b/openssh/ssh_config.5 @@ -311,6 +311,11 @@ the result of a successful key exchange, or using GSSAPI user authentication. The default is .Dq yes . +.It Cm GssapiKeyExchange +Specifies whether key exchange based on GSSAPI may be used. When using +GSSAPI key exchange the server need not have a host key. +The default is +.Dq yes . .It Cm GssapiDelegateCredentials Specifies whether GSSAPI credentials will be delegated (forwarded) to the server. diff --git a/openssh/sshconnect2.c b/openssh/sshconnect2.c index 38cef29..d525f64 100644 --- a/openssh/sshconnect2.c +++ b/openssh/sshconnect2.c @@ -90,6 +90,7 @@ ssh_kex2(char *host, struct sockaddr *hostaddr) xxx_hostaddr = hostaddr; #ifdef GSSAPI + if (options.gss_keyex) { /* Add the GSSAPI mechanisms currently supported on this client to * the key exchange algorithm proposal */ orig = myproposal[PROPOSAL_KEX_ALGS]; @@ -99,6 +100,7 @@ ssh_kex2(char *host, struct sockaddr *hostaddr) myproposal[PROPOSAL_KEX_ALGS]=xmalloc(len); snprintf(myproposal[PROPOSAL_KEX_ALGS],len,"%s,%s",gss,orig); } + } #endif if (options.ciphers == (char *)-1) { @@ -131,7 +133,7 @@ ssh_kex2(char *host, struct sockaddr *hostaddr) #ifdef GSSAPI /* If we've got GSSAPI algorithms, then we also support the * 'null' hostkey, as a last resort */ - if (gss) { + if (options.gss_keyex && gss) { orig=myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]; len = strlen(orig)+sizeof(",null"); myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]=xmalloc(len); @@ -496,17 +498,16 @@ input_userauth_pk_ok(int type, u_int32_t seq, void *ctxt) int userauth_gssapi(Authctxt *authctxt) { - int i; Gssctxt *gssctxt; - static int tries=0; - - /* For now, we only make one attempt at this. We could try offering - * the server different GSSAPI OIDs until we get bored, I suppose. - */ - if (tries++>0) return 0; + static int mech=0; if (datafellows & SSH_OLD_GSSAPI) return 0; + /* Try each mechanism in turn. Give up if we've tried all + supported mechanisms. + */ + if (mech==GSS_LAST_ENTRY) return 0; + /* Initialise as much of our context as we can, so failures can be * trapped before sending any packets. */ @@ -536,17 +537,19 @@ userauth_gssapi(Authctxt *authctxt) * This may not be the case - we should use something along * the lines of the code in gss_genr to remove the ones that * aren't supported */ - packet_put_int(GSS_LAST_ENTRY); - for (i=0;imethoddata; recv_tok.value=packet_get_string(&slen); -- 2.45.1