Ejemplo n.º 1
0
void
ssh_eap_protocol_send_response(SshEapProtocol protocol,
                               SshEap eap,
                               SshBuffer buf)
{
  SSH_PRECOND(eap != NULL);
  SSH_PRECOND(ssh_eap_isauthenticator(eap) == 0);

  SSH_ASSERT(ssh_eap_packet_isvalid(buf));

  /* Send packet */

  ssh_eap_remember_packet(eap, buf);
  ssh_eap_send_packet(eap, buf);
}
Ejemplo n.º 2
0
void
ssh_eap_protocol_request_token_with_args(SshEap eap,
                                         SshUInt8 eap_type,
                                         SshEapTokenType type, 
                                         unsigned char *input,
                                         SshUInt16 input_len)
{
  SshBufferStruct   buf;
  SshEapTokenStruct token;
  
  SSH_PRECOND(eap != NULL);

  SSH_DEBUG(SSH_D_MIDOK,("requesting token of type %d from user %u", 
                         type, input_len));
 
  eap->waiting_for_callback = 1;

  buf.dynamic = FALSE;
  buf.buf = (unsigned char*)&token;
  buf.alloc = sizeof(token);
  buf.offset = 0;
  buf.end = buf.alloc;

  token.token.buffer.dptr = input;
  token.token.buffer.len  = input_len;

  token.type = type;

  ssh_eap_send_signal(eap,
                      eap_type,
                      SSH_EAP_SIGNAL_NEED_TOKEN,
                      &buf);
}
Ejemplo n.º 3
0
void*
ssh_eap_protocol_get_params(SshEapProtocol protocol)
{
  SSH_PRECOND(protocol != NULL);

  return protocol->params;
}
Ejemplo n.º 4
0
void*
ssh_eap_protocol_get_state(SshEapProtocol protocol)
{
  SSH_PRECOND(protocol != NULL);

  return protocol->state;
}
Ejemplo n.º 5
0
void
ssh_eap_send_signal(SshEap eap,
                    SshUInt8 type,
                    SshEapSignal signal,
                    SshBuffer buf)
{
  SSH_PRECOND(eap != NULL);

  if (eap->destroy_pending == 1
      || eap->params == NULL
      || eap->params->signal_cb == NULL_FNPTR)
    {
      SSH_DEBUG(SSH_D_ERROR,
                ("incapable of delivering signal, discarding it"));
      if (buf) 
        ssh_buffer_free(buf);
      return;
    }

  SSH_EAP_CB(eap, eap->params->signal_cb(eap,
					 type,
					 signal,
					 buf,
					 eap->ctx));
}
Ejemplo n.º 6
0
SshBuffer
ssh_eap_create_reply(SshEap eap, SshUInt16 len, SshUInt8 type)
{
  SshBuffer pkt;

  SSH_PRECOND(eap != NULL);

  pkt = ssh_buffer_allocate();

  if (pkt == NULL)
    return NULL;

  SSH_ASSERT(eap->id_isinit == 1);

  if (!ssh_eap_packet_build_hdr_with_type(pkt,
					  SSH_EAP_CODE_REPLY,
					  eap->id,
					  len,
					  type))
    {
      ssh_buffer_free(pkt);
      return NULL;
    }
  return pkt;
}
Ejemplo n.º 7
0
SshRadiusUrlStatus
ssh_radius_url_add_server(SshRadiusClientServerInfo s_info, unsigned char *url)
{
  unsigned char *scheme, *host, *port, *username, *password, *path;
  const unsigned char *real_port, *real_secret;
  Boolean res;

  SSH_PRECOND(url != NULL);

  real_port = NULL;
  scheme = host = port = username = password = path = NULL;

  res = ssh_url_parse(url, &scheme, &host, &port, &username,
                      &password, &path);

  if (res == FALSE)
    goto fail;

  res = FALSE;

  if (scheme == NULL)
    goto fail;

  if (ssh_usstrcmp(scheme, "radius") != 0)
    goto fail;

  if (host == NULL)
    goto fail;

  real_port =   (real_port !=  NULL ? port : (unsigned char *)"1812");
  real_secret = (password != NULL ? password : (unsigned char *)"");

  res = ssh_radius_client_server_info_add_server(s_info,
                                                 host,
                                                 real_port,
                                                 real_port,
                                                 real_secret,
                                                 ssh_ustrlen(real_secret));

 fail:
  if (scheme != NULL)
    ssh_free(scheme);

  if (host != NULL)
    ssh_free(host);

  if (port != NULL)
    ssh_free(port);

  if (username != NULL)
    ssh_free(username);

  if (password != NULL)
    ssh_free(password);

  if (path != NULL)
    ssh_free(path);

  return res;
}
Ejemplo n.º 8
0
unsigned long
ssh_eap_protocol_get_mru(SshEapProtocol protocol, SshEap eap)
{
  SSH_PRECOND(eap != NULL);

  return (eap->con != NULL ? eap->con->mru : 1400);
}
Ejemplo n.º 9
0
Boolean
ssh_eap_isauthenticator(SshEap eap)
{
  SSH_PRECOND(eap != NULL);

  return (eap->is_authenticator == 1 ? TRUE : FALSE);
}
Ejemplo n.º 10
0
void
ssh_eap_protocol_master_session_key(SshEap eap,
				    const unsigned char *session_key,
				    size_t session_key_len)
{
  SSH_PRECOND(eap->msk == NULL);

  eap->msk = ssh_memdup(session_key, session_key_len);
  eap->msk_len = session_key_len;
}
Ejemplo n.º 11
0
void
ssh_eap_protocol_auth_fail(SshEapProtocol protocol,
                           SshEap eap,
                           SshEapSignal sig,
                           SshBuffer buf)
{
  SshUInt8 id;

  SSH_PRECOND(eap != NULL);

  eap->method_done = 1;
  eap->method_ok = 0;

#ifdef SSHDIST_RADIUS
  ssh_eap_radius_reset(eap);
#endif /* SSHDIST_RADIUS */

  ssh_eap_cancel_auth_timeout(eap);

  /* Send the packet first, and then the signal */
  if (eap->is_authenticator == 1 &&
      ssh_eap_send_failure(eap) == FALSE)
    {
      eap->id_isrecv = 0;
      return;
    }
  eap->id_isrecv = 0;

  if (protocol != NULL)
    {
      id = protocol->impl->id;
    }
  else
    {
      id = eap->previous_eap_type;
    }

  switch (sig)
    {
    case SSH_EAP_SIGNAL_AUTH_FAIL_USERNAME:
      break;
    case SSH_EAP_SIGNAL_AUTH_FAIL_NEGOTIATION:
      buf = NULL;
      break;
    default:
      buf = NULL;
      if (ssh_eap_isauthenticator(eap) == TRUE)
        sig = SSH_EAP_SIGNAL_AUTH_FAIL_REPLY;
      else
        sig = SSH_EAP_SIGNAL_AUTH_FAIL_AUTHENTICATOR;
      break;
    }

  ssh_eap_send_signal(eap, id, sig, buf);
}
Ejemplo n.º 12
0
void
ssh_eap_protocol_auth_ok(SshEapProtocol protocol,
                         SshEap eap,
                         SshEapSignal sig,
                         SshBuffer buf)
{
  SshUInt8 id;

  SSH_PRECOND(eap != NULL);

  eap->method_done = 1;
  eap->method_ok = 1;

#ifdef SSHDIST_RADIUS
  ssh_eap_radius_reset(eap);
#endif /* SSHDIST_RADIUS */

  ssh_eap_cancel_auth_timeout(eap);

  if (protocol != NULL)
    {
      id = protocol->impl->id;
    }
  else
    {
      id = eap->previous_eap_type;
    }

  if (ssh_eap_isauthenticator(eap))
    {
      /* Send the packet first, and then the signal */
      if (ssh_eap_send_success(eap) == TRUE)
        {
          eap->id_isrecv = 0;
          if (sig != SSH_EAP_SIGNAL_AUTH_OK_USERNAME)
            {
              sig = SSH_EAP_SIGNAL_AUTH_AUTHENTICATOR_OK;
              buf = NULL;
            }

          ssh_eap_send_signal(eap, id, sig, buf);
        }
      eap->id_isrecv = 0;
    }
  else
    {
      ssh_eap_send_signal(eap,
                          id,
                          SSH_EAP_SIGNAL_AUTH_PEER_MAYBE_OK,
                          NULL);
    }
}
void *ssh_strdup (const void * p)
{
  const char  * str;
  char        * cp;

  SSH_PRECOND(p != NULL);

  str = (const char *) p;

  if ((cp = (char *) ssh_malloc(strlen(str) + 1)) == NULL)
    return NULL;

  strcpy(cp, str);

  return (void *) cp;
}
Ejemplo n.º 14
0
static void
ssh_eap_timeout(SshEap eap)
{
  SSH_PRECOND(eap != NULL);

  /* Reset the EAP instance, so that no further signals
     are delivered untill action by the owner of the
     instance. */
  ssh_eap_reset(eap);

  /* Signal the caller that authentication has failed due to a timeout */

  SSH_DEBUG(SSH_D_MIDOK,("EAP authentication timed out"));

  ssh_eap_send_signal(eap, eap->previous_eap_type,
		      SSH_EAP_SIGNAL_AUTH_FAIL_TIMEOUT, NULL);
}
Ejemplo n.º 15
0
static SshRadiusUrlStatus
ssh_radius_url_parse_nas_id(unsigned char *url, unsigned char **result)
{
  Boolean res;
  SshRadiusUrlStatus url_status;
  unsigned char *scheme, *name;

  SSH_PRECOND(url != NULL);

  /* Note that we can not detect if this failed due
     to an out of memory error! If we could, then we
     would provide more than an equivalent of FALSE/TRUE
     in the return code. */

  res = ssh_url_parse(url, &scheme, NULL, NULL, &name, NULL, NULL);

  if (res == FALSE)
    return SSH_RADIUS_URL_MALFORMED;

  url_status = SSH_RADIUS_URL_INVALID_SCHEME;

  if (scheme == NULL)
    goto fail;

  if (ssh_usstrcmp(scheme, "radius") != 0)
    goto fail;

  ssh_free(scheme);
  *result = name;

  if (name == NULL)
    return SSH_RADIUS_URL_EXPECTING_NAS_ID;

  return SSH_RADIUS_URL_STATUS_SUCCESS;

 fail:
  if (scheme != NULL)
    ssh_free(scheme);

  if (name != NULL)
    ssh_free(name);

  *result = NULL;

  return url_status;
}
Ejemplo n.º 16
0
SshRadiusUrlStatus
ssh_radius_url_isok(unsigned char *url)
{
  SshRadiusUrlAvpSetStruct avp_set;
  SshRadiusUrlStatus url_status;
  SshRadiusClientServerInfo s_info;
  SshRadiusClientParamsStruct params;

  SSH_PRECOND(url != NULL);

  /* Check Params specification */

  url_status = ssh_radius_url_init_params(&params, url);

  if (url_status != SSH_RADIUS_URL_STATUS_SUCCESS)
    return url_status;

  ssh_radius_url_uninit_params(&params);

  /* Check server spec. */

  s_info = ssh_radius_client_server_info_create();

  if (s_info == NULL)
    return SSH_RADIUS_URL_OUT_OF_MEMORY;

  url_status = ssh_radius_url_add_server(s_info, url);

  ssh_radius_client_server_info_destroy(s_info);

  if (url_status != SSH_RADIUS_URL_STATUS_SUCCESS)
    return url_status;

  /* Check AVP spec */

  url_status = ssh_radius_url_init_avpset(&avp_set, url);

  if (url_status != SSH_RADIUS_URL_STATUS_SUCCESS)
    return url_status;

  ssh_radius_url_uninit_avpset(&avp_set);

  return SSH_RADIUS_URL_STATUS_SUCCESS;
}
Ejemplo n.º 17
0
void
ssh_eap_send_packet(SshEap eap, SshBuffer buf)
{
  SSH_PRECOND(eap != NULL);

  /* Remember the last packet we sent out */

  eap->previous_eap_code = ssh_eap_packet_get_code(buf);

  if (ssh_eap_packet_get_length(buf) > 4)
    eap->previous_eap_type = ssh_eap_packet_get_type(buf);
  
  /* Assume that the eap->con has been destroyed, if we
     have been destroyed (which may well be the case). */

  if (eap->destroy_pending == 0)
    {
      SSH_EAP_CB(eap,
                 ssh_eap_connection_output_packet(eap->con,buf));
    }
}
Ejemplo n.º 18
0
/* Destroys the connection context. */
void tcp_connect_destroy_ctx(ConnectContext c)
{
    SSH_DEBUG(4, ("Destroying ConnectContext..."));
    SSH_PRECOND(c != NULL);
    if (c->handle)
        ssh_operation_abort(c->handle);

    ssh_cancel_timeout(&c->timeout);
    ssh_free(c->local_address);
    ssh_free(c->host_name);
    ssh_free(c->host_addresses);
    ssh_free(c->socks_host);
    ssh_free(c->socks_addresses);
    ssh_free(c->user_name);
    ssh_free(c->socks_exceptions);
    if (c->socks_buf)
        ssh_buffer_free(c->socks_buf);
    if (c->stream)
        ssh_stream_destroy(c->stream);
    if (c->upper_handle)
        ssh_operation_unregister(c->upper_handle);

    ssh_free(c);
}
Ejemplo n.º 19
0
/* Parses a given comma-separated list to tokens, which are stored in
   a SshDlList. The list is allocated and returned by this
   function. On error, returns NULL. */
SshDlList ssh_config_parse_list(char *string,
                                SshParameterValidityProc function,
                                void *context)
{
  char *rest;
  char *current;
  SshDlList list;
  
  SSH_PRECOND(string != NULL);

  list = ssh_dllist_allocate();

  rest = string;

  while (strlen(rest) != 0 && (current = ssh_name_list_get_name(rest)) != NULL)
    {
      char *temp;
      int i, j;
      
      rest += strlen(current);
      if (*rest == ',')
        rest++;

      /* strip whitespaces and non-printable characters */
      temp = ssh_xcalloc(strlen(current) + 1, sizeof(char));
      
      for (i = 0, j = 0; i < strlen(current) ; i ++)
        if(isascii(current[i]) && isprint(current[i]) && !isspace(current[i]))
          {
            temp[j] = current[i];
            j++;
          }
      
      temp[j] = '\0';
      ssh_xfree(current);
      current = temp;

      /* If validity function is given, invoke it to check the current
         parameter.*/
      if (function)
        if ((*function)(current, context))
          {
            ssh_xfree(current);
            continue;
          }
      
      if (ssh_dllist_add_item(list, (void *)current, SSH_DLLIST_END) !=
          SSH_DLLIST_OK)
        {
          SSH_DEBUG(0, ("list operation gave error."));
          ssh_dllist_rewind(list);
          while (ssh_dllist_is_empty(list))
            {
              char *to_be_deleted;
              to_be_deleted = ssh_dllist_delete_current(list);
              ssh_xfree(to_be_deleted);
            }

          ssh_dllist_free(list);
          
          return NULL;
        }      
    }

  return list;
}
Ejemplo n.º 20
0
static SshRadiusUrlStatus
ssh_radius_url_add_avp(SshRadiusUrlAvpSet avp_set,
                       const SshRadiusAvpInfoStruct *avp_info,
                       unsigned char *value,
                       size_t value_len)
{
  unsigned long val;
  SshRadiusUrlStatus url_status;

  SSH_PRECOND(avp_set != NULL);
  SSH_PRECOND(avp_info != NULL);

  /* Try to allow for "magic keyword" substituion for selected
     parameter values. */

  if (avp_info->value_type == SSH_RADIUS_AVP_VALUE_INTEGER)
    {
      url_status =
        ssh_radius_url_add_avp_by_type(avp_set, avp_info, value, value_len);

      if (url_status != SSH_RADIUS_URL_STATUS_NONE)
        return url_status;
    }

  /* Perform setting based on type */

  switch (avp_info->value_type)
    {
    case SSH_RADIUS_AVP_VALUE_TEXT:
      if (ssh_radius_url_set_avpset_avp(avp_set, avp_info->type,
                                        (SshUInt8 *) value,
                                        (SshUInt8)value_len)
          == FALSE)
        return SSH_RADIUS_URL_OUT_OF_MEMORY;
      break;

    case SSH_RADIUS_AVP_VALUE_TAG_INTEGER:
    case SSH_RADIUS_AVP_VALUE_TAG_STRING:
    case SSH_RADIUS_AVP_VALUE_IPV6_ADDRESS:
      SSH_DEBUG(SSH_D_FAIL,("TAG and IPV6 attributes not yet supported"));
      return SSH_RADIUS_URL_UNKNOWN_AVP_TYPE;
      break;

    case SSH_RADIUS_AVP_VALUE_TIME:
    case SSH_RADIUS_AVP_VALUE_INTEGER:
      {
        SshUInt8 number_buf[4];
        val = (value != NULL ? ssh_ustrtol(value, NULL, 0) : 0);
        SSH_PUT_32BIT(number_buf, val);

        if (ssh_radius_url_set_avpset_avp(avp_set, avp_info->type,
                                          number_buf, 4) == FALSE)
          return SSH_RADIUS_URL_OUT_OF_MEMORY;
      }
      break;

      /* Convert IPv4 address to 32-bit integer */
    case SSH_RADIUS_AVP_VALUE_ADDRESS:
      {
        SshIpAddrStruct ip_addr;
        SshUInt8 number_buf[4];

        if (value == NULL)
          return SSH_RADIUS_URL_INVALID_AVP_VALUE;

        if (ssh_ipaddr_parse(&ip_addr, value) == FALSE)
          return SSH_RADIUS_URL_INVALID_AVP_VALUE;

        if (SSH_IP_IS4(&ip_addr) == FALSE)
          return SSH_RADIUS_URL_INVALID_AVP_VALUE;

        SSH_PUT_32BIT(number_buf, SSH_IP4_TO_INT(&ip_addr));

        if (ssh_radius_url_set_avpset_avp(avp_set, avp_info->type,
                                          number_buf, 4) == FALSE)
          return SSH_RADIUS_URL_OUT_OF_MEMORY;
      }
      break;

    default:
      SSH_DEBUG(SSH_D_FAIL,
                ("Unknown RADIUS attribute value type %d!",
                 avp_info->value_type));
      return SSH_RADIUS_URL_UNKNOWN_AVP_TYPE;
    }

  return SSH_RADIUS_URL_STATUS_SUCCESS;
}
Ejemplo n.º 21
0
Boolean
ssh_radius_url_set_avpset_avp(SshRadiusUrlAvpSet avp_set,
                              SshRadiusAvpType avp_type,
                              SshUInt8 *buf,
                              SshUInt8 len)
{
  size_t i;
  SshUInt8 *new_buf;
  SshRadiusUrlAvp avp;

  SSH_PRECOND(avp_set != NULL);

  /* First see if we can get a buffer for the contents of the AVP */

  avp = NULL;
  new_buf = NULL;

  if (buf != NULL)
    {
      new_buf = ssh_malloc(len);
      if (new_buf == NULL)
        return FALSE;

      memcpy(new_buf, buf, len);
    }

  /* .. then try to enlarge the AVP set in such a manner that it does
     not break if we run out of memory.. */

  for (i = 0; i < avp_set->navps; i++)
    {
      if (avp_set->avp[i].type == avp_type)
        break;
    }

  if (i == avp_set->navps)
    {
      avp = ssh_malloc((avp_set->navps+1)*sizeof(SshRadiusUrlAvpStruct));

      if (avp == NULL)
        return FALSE;

      avp_set->navps++;

      memcpy(avp, avp_set->avp,
             (avp_set->navps)*sizeof(SshRadiusUrlAvpStruct));

      ssh_free(avp_set->avp);
      avp_set->avp = avp;

      avp[i].type = 0;
      avp[i].buf = NULL;
      avp[i].len = 0;
    }
  else
    {
      avp = avp_set->avp;
      
      if (avp[i].buf != NULL)
        ssh_free(avp[i].buf);
      avp[i].buf = NULL;
      avp[i].len = 0;
      avp[i].type = 0;
    }


  avp[i].buf = new_buf;
  avp[i].len = len;
  avp[i].type = avp_type;
  return TRUE;
}
Ejemplo n.º 22
0
/*------------------------------------------------------------------------
  Waits multiple events to occur.
  ------------------------------------------------------------------------*/
__inline Boolean
ssh_event_wait_multiple(unsigned long event_cnt,
                        SshEvent *events, 
                        SshWCB wcb)
{
  unsigned int i = 0;
  void *wait_block = NULL;
  SshOsEvent *wait_objects;
#ifdef _WIN32_WCE
  DWORD status;
  DWORD wait_time = INFINITE;
  BOOL wait_all = TRUE;
#else
  NTSTATUS status = STATUS_SUCCESS;
  LARGE_INTEGER t, *pt = &t;
  WAIT_TYPE wait_type = WaitAll;
#endif /* _WIN32_WCE */

  SSH_PRECOND(events != NULL);
  SSH_PRECOND(event_cnt > 0 && event_cnt < SSH_EVT_WAIT_MAX_CNT);
  SSH_PRECOND(wcb != NULL);

#ifdef _WIN32_WCE
  if (wcb->mode == SSH_EVT_WAIT_MODE_ANY)
    wait_all = FALSE;

  if (wcb->wait_time_ms != SSH_EVT_WAIT_INFINITE)
    wait_time = wcb->wait_time_ms;
#else 
  /* Set wait mode */
  if (wcb->mode == SSH_EVT_WAIT_MODE_ANY)
    wait_type = WaitAny;

  /* Calculate wait timeout */
  if (wcb ->wait_time_ms == SSH_EVT_WAIT_INFINITE)
    pt = NULL;
  else
    pt->QuadPart = (wcb->wait_time_ms * (-10000));
    

  /* Allocate memory for wait block if not allready initialized */
  if (!wcb->reserved[1])
    {
      wait_block = wcb->reserved[1] = 
        ssh_calloc(event_cnt, sizeof(KWAIT_BLOCK));

      if (wait_block == NULL)
        {
          SSH_DEBUG(SSH_D_FAIL, ("Failed to allocate wait block"));
          return FALSE;
        }
    }
#endif /* _WIN32_WCE */

  /* Allocate memory for objects if not already initialized */
  if (!wcb->reserved[0])
    {
      wait_objects = ssh_calloc(event_cnt, sizeof(events[0]->os_event));
      if (wait_objects == NULL)
        {
          SSH_DEBUG(SSH_D_FAIL, ("Failed to allocate memory for objects"));
          ssh_free(wait_block);
          return FALSE;
        }

      wcb->reserved[0] = wait_objects;

      /* Init object array with events that we are interested in */
      for (i = 0; i < event_cnt; i++)
        wait_objects[i] = events[i]->os_event;
    }

  /* Wait for events to occur */
#ifdef _WIN32_WCE
  status = WaitForMultipleObjects(event_cnt, wcb->reserved[0], 
                                  wait_all, wait_time);

  if ((status < WAIT_OBJECT_0)
      || (status >= (WAIT_OBJECT_0 + event_cnt)))
    {
      DWORD error = GetLastError();

      SSH_DEBUG(SSH_D_FAIL, ("Wait failed (%08X, %08X)", status, error));
      return FALSE;
    }
#else
  status = KeWaitForMultipleObjects(event_cnt, 
                                    wcb->reserved[0],
                                    wait_type, 
                                    Executive, 
                                    KernelMode, 
                                    FALSE, 
                                    pt, 
                                    wcb->reserved[1]);

  /* Check wait result */
  if (!NT_SUCCESS(status))
    {
      SSH_DEBUG(SSH_D_FAIL, ("Wait failed (%08X)", status));
      return FALSE;
    }
#endif /* _WIN32_WCE */

  if ((unsigned long)status < event_cnt)
    {
      /* Clear event state */
      ssh_event_reset(events[status]);

      /* Execute possible associated event handler routine */
      if (events[status]->event_cb)
        events[status]->event_cb(events[status]->context);
    }

  return TRUE;
}
Ejemplo n.º 23
0
char *ssh_snlist_intersection(const char *src1,
			      const char *src2)
{
  int total_len1, total_len2, name_len1, name_len2, max_len1, max_len2;
  Boolean prev;
  const char *tmp;
  char *dest, *dest_start;

  SSH_PRECOND(src1 != NULL);
  SSH_PRECOND(src2 != NULL);
  
  /* Set up the destination buffer. */

  prev = FALSE;
  if ((dest = ssh_malloc(strlen(src1) + 1)) == NULL)
    return NULL;
  dest_start = dest;

  /* Start looping the two namelists. And seek for names of same
     length and only then compare. */

  max_len1 = strlen(src1);
  max_len2 = strlen(src2);
  for (total_len1 = 0; total_len1 < max_len1; )
    {
      /* Get name lenght */
      name_len1 = ssh_snlist_name_len(src1);

      /* Start inner loop */
      for (tmp = src2, total_len2 = 0; total_len2 < max_len2; )
        {
          name_len2 = ssh_snlist_name_len(tmp);

          if (name_len2 == name_len1)
            {
              if (memcmp(src1, tmp, name_len1) == 0)
                {
                  if (prev)
                    *dest++ = ',';
                  prev = TRUE;
                  memcpy(dest, src1, name_len1);
                  dest += name_len1;
                  break;
                }
            }
          total_len2 += name_len2;

          /* Tricky part is to notice that we need to check for terminating
             zero, and quit if found. */
          tmp += name_len2;
          if (*tmp == '\0')
            break;
          /* Not zero so get past that comma. */
          tmp++;
        }

      total_len1 += name_len1;

      src1 += name_len1;
      if (*src1 == '\0')
        break;
      src1++;
    }
  /* In any case place zero terminator to the namelist. */
  *dest = '\0';
  return dest_start;
}