Coverage Report

Created: 2026-09-28 06:47

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/strongswan/src/libradius/radius_client.c
Line
Count
Source
1
/*
2
 * Copyright (C) 2009 Martin Willi
3
 *
4
 * Copyright (C) secunet Security Networks AG
5
 *
6
 * This program is free software; you can redistribute it and/or modify it
7
 * under the terms of the GNU General Public License as published by the
8
 * Free Software Foundation; either version 2 of the License, or (at your
9
 * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
10
 *
11
 * This program is distributed in the hope that it will be useful, but
12
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14
 * for more details.
15
 */
16
17
#include "radius_client.h"
18
#include "radius_config.h"
19
20
#include <unistd.h>
21
#include <errno.h>
22
23
#include <utils/debug.h>
24
#include <networking/host.h>
25
#include <collections/linked_list.h>
26
#include <threading/condvar.h>
27
#include <threading/mutex.h>
28
29
typedef struct private_radius_client_t private_radius_client_t;
30
31
/**
32
 * Private data of an radius_client_t object.
33
 */
34
struct private_radius_client_t {
35
36
  /**
37
   * Public radius_client_t interface.
38
   */
39
  radius_client_t public;
40
41
  /**
42
   * Selected RADIUS server configuration
43
   */
44
  radius_config_t *config;
45
46
  /**
47
   * RADIUS servers State attribute
48
   */
49
  chunk_t state;
50
51
  /**
52
   * EAP MSK, from MPPE keys
53
   */
54
  chunk_t msk;
55
};
56
57
/**
58
 * Save the state attribute to include in further request
59
 */
60
static void save_state(private_radius_client_t *this, radius_message_t *msg)
61
0
{
62
0
  enumerator_t *enumerator;
63
0
  int type;
64
0
  chunk_t data;
65
66
0
  enumerator = msg->create_enumerator(msg);
67
0
  while (enumerator->enumerate(enumerator, &type, &data))
68
0
  {
69
0
    if (type == RAT_STATE)
70
0
    {
71
0
      free(this->state.ptr);
72
0
      this->state = chunk_clone(data);
73
0
      enumerator->destroy(enumerator);
74
0
      return;
75
0
    }
76
0
  }
77
0
  enumerator->destroy(enumerator);
78
  /* no state attribute found, remove state */
79
0
  chunk_free(&this->state);
80
0
}
81
82
METHOD(radius_client_t, request, radius_message_t*,
83
  private_radius_client_t *this, radius_message_t *req)
84
0
{
85
0
  radius_socket_t *socket;
86
0
  radius_message_t *res;
87
88
  /* add our NAS-Identifier */
89
0
  req->add(req, RAT_NAS_IDENTIFIER,
90
0
       this->config->get_nas_identifier(this->config));
91
  /* add State attribute, if server sent one */
92
0
  if (this->state.ptr)
93
0
  {
94
0
    req->add(req, RAT_STATE, this->state);
95
0
  }
96
0
  socket = this->config->get_socket(this->config);
97
0
  DBG1(DBG_CFG, "sending RADIUS %N to server '%s'", radius_message_code_names,
98
0
     req->get_code(req), this->config->get_name(this->config));
99
100
0
  res = socket->request(socket, req);
101
0
  if (res)
102
0
  {
103
0
    DBG1(DBG_CFG, "received RADIUS %N from server '%s'",
104
0
       radius_message_code_names, res->get_code(res),
105
0
       this->config->get_name(this->config));
106
#if DEBUG_LEVEL >= 3
107
    chunk_t data = res->get_encoding(res);
108
    DBG3(DBG_CFG, "%B", &data);
109
#endif
110
111
0
    save_state(this, res);
112
0
    if (res->get_code(res) == RMC_ACCESS_ACCEPT)
113
0
    {
114
0
      chunk_clear(&this->msk);
115
0
      this->msk = socket->decrypt_msk(socket, req, res);
116
0
    }
117
0
    this->config->put_socket(this->config, socket, TRUE);
118
0
    return res;
119
0
  }
120
0
  this->config->put_socket(this->config, socket, FALSE);
121
0
  return NULL;
122
0
}
123
124
METHOD(radius_client_t, get_msk, chunk_t,
125
  private_radius_client_t *this)
126
0
{
127
0
  return this->msk;
128
0
}
129
130
METHOD(radius_client_t, destroy, void,
131
  private_radius_client_t *this)
132
0
{
133
0
  this->config->destroy(this->config);
134
0
  chunk_clear(&this->msk);
135
0
  free(this->state.ptr);
136
0
  free(this);
137
0
}
138
139
/**
140
 * See header
141
 */
142
radius_client_t *radius_client_create(radius_config_t *config)
143
0
{
144
0
  private_radius_client_t *this;
145
146
0
  INIT(this,
147
0
    .public = {
148
0
      .request = _request,
149
0
      .get_msk = _get_msk,
150
0
      .destroy = _destroy,
151
0
    },
152
0
    .config = config,
153
0
  );
154
155
0
  return &this->public;
156
0
}