All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
session.c
Go to the documentation of this file.
1 /*
2  * session.c session management
3  *
4  * Version: $Id: 75fa0cee4ad6e0ef2f2561c49e9a8c97b16e973e $
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  *
20  * Copyright 2000,2006 The FreeRADIUS server project
21  */
22 
23 RCSID("$Id: 75fa0cee4ad6e0ef2f2561c49e9a8c97b16e973e $")
24 
25 #include <freeradius-devel/radiusd.h>
26 #include <freeradius-devel/modules.h>
27 #include <freeradius-devel/rad_assert.h>
28 
29 #ifdef HAVE_SYS_WAIT_H
30 #include <sys/wait.h>
31 #endif
32 
33 #ifdef WITH_SESSION_MGMT
34 /*
35  * End a session by faking a Stop packet to all accounting modules.
36  */
37 int session_zap(REQUEST *request, uint32_t nasaddr, uint32_t nas_port,
38  char const *user,
39  char const *sessionid, uint32_t cliaddr, char proto,
40  int session_time)
41 {
42  REQUEST *stopreq;
43  VALUE_PAIR *vp, *userpair;
44  int ret;
45 
46  stopreq = request_alloc_fake(request);
47  rad_assert(stopreq != NULL);
48  rad_assert(stopreq->packet != NULL);
49  stopreq->packet->code = PW_CODE_ACCOUNTING_REQUEST; /* just to be safe */
50  stopreq->listener = request->listener;
51 
52  /* Hold your breath */
53 #define PAIR(n,v,e) do { \
54  if(!(vp = fr_pair_afrom_num(stopreq->packet,n, 0))) { \
55  talloc_free(stopreq); \
56  ERROR("no memory"); \
57  fr_pair_list_free(&(stopreq->packet->vps)); \
58  return 0; \
59  } \
60  vp->e = v; \
61  fr_pair_add(&(stopreq->packet->vps), vp); \
62  } while(0)
63 
64 #define INTPAIR(n,v) PAIR(n,v,vp_integer)
65 
66 #define IPPAIR(n,v) PAIR(n,v,vp_ipaddr)
67 
68 #define STRINGPAIR(n,v) do { \
69  if(!(vp = fr_pair_afrom_num(stopreq->packet,n, 0))) { \
70  talloc_free(stopreq); \
71  ERROR("no memory"); \
72  fr_pair_list_free(&(stopreq->packet->vps)); \
73  return 0; \
74  } \
75  fr_pair_value_strcpy(vp, v); \
76  fr_pair_add(&(stopreq->packet->vps), vp); \
77  } while(0)
78 
79  INTPAIR(PW_ACCT_STATUS_TYPE, PW_STATUS_STOP);
80  IPPAIR(PW_NAS_IP_ADDRESS, nasaddr);
81  INTPAIR(PW_ACCT_DELAY_TIME, 0);
82  STRINGPAIR(PW_USER_NAME, user);
83  userpair = vp;
84  INTPAIR(PW_NAS_PORT, nas_port);
85  STRINGPAIR(PW_ACCT_SESSION_ID, sessionid);
86  if(proto == 'P') {
87  INTPAIR(PW_SERVICE_TYPE, PW_FRAMED_USER);
88  INTPAIR(PW_FRAMED_PROTOCOL, PW_PPP);
89  } else if(proto == 'S') {
90  INTPAIR(PW_SERVICE_TYPE, PW_FRAMED_USER);
91  INTPAIR(PW_FRAMED_PROTOCOL, PW_SLIP);
92  } else {
93  INTPAIR(PW_SERVICE_TYPE, PW_LOGIN_USER); /* A guess, really */
94  }
95  if(cliaddr != 0)
96  IPPAIR(PW_FRAMED_IP_ADDRESS, cliaddr);
97  INTPAIR(PW_ACCT_SESSION_TIME, session_time);
98  INTPAIR(PW_ACCT_INPUT_OCTETS, 0);
99  INTPAIR(PW_ACCT_OUTPUT_OCTETS, 0);
100  INTPAIR(PW_ACCT_INPUT_PACKETS, 0);
101  INTPAIR(PW_ACCT_OUTPUT_PACKETS, 0);
102 
103  stopreq->username = userpair;
104  stopreq->password = NULL;
105 
106  ret = rad_accounting(stopreq);
107 
108  /*
109  * We've got to clean it up by hand, because no one else will.
110  */
111  talloc_free(stopreq);
112 
113  return ret;
114 }
115 
116 #ifndef __MINGW32__
117 
118 /*
119  * Check one terminal server to see if a user is logged in.
120  *
121  * Return values:
122  * 0 The user is off-line.
123  * 1 The user is logged in.
124  * 2 Some error occured.
125  */
126 int rad_check_ts(uint32_t nasaddr, uint32_t nas_port, char const *user,
127  char const *session_id)
128 {
129  pid_t pid, child_pid;
130  int status;
131  char buffer[INET_ADDRSTRLEN];
132  char port[11];
133  RADCLIENT *cl;
134  fr_ipaddr_t ipaddr;
135 
136  ipaddr.af = AF_INET;
137  ipaddr.ipaddr.ip4addr.s_addr = nasaddr;
138 
139  /*
140  * Find NAS type.
141  */
142  cl = client_find_old(&ipaddr);
143  if (!cl) {
144  /*
145  * Unknown NAS, so trusting radutmp.
146  */
147  DEBUG2("checkrad: Unknown NAS %s, not checking",
148  inet_ntop(ipaddr.af, &ipaddr.ipaddr, buffer, sizeof(buffer)));
149 
150  return 1;
151  }
152 
153  /*
154  * No nas_type, or nas type 'other', trust radutmp.
155  */
156  if (!cl->nas_type || (cl->nas_type[0] == '\0') || (strcmp(cl->nas_type, "other") == 0)) {
157  DEBUG2("checkrad: No NAS type, or type \"other\" not checking");
158  return 1;
159  }
160 
161  /*
162  * Fork.
163  */
164  if ((pid = rad_fork()) < 0) { /* do wait for the fork'd result */
165  ERROR("Accounting: Failed in fork(): Cannot run checkrad\n");
166  return 2;
167  }
168 
169  if (pid > 0) {
170  child_pid = rad_waitpid(pid, &status);
171 
172  /*
173  * It's taking too long. Stop waiting for it.
174  *
175  * Don't bother to kill it, as we don't care what
176  * happens to it now.
177  */
178  if (child_pid == 0) {
179  ERROR("Check-TS: timeout waiting for checkrad");
180  return 2;
181  }
182 
183  if (child_pid < 0) {
184  ERROR("Check-TS: unknown error in waitpid()");
185  return 2;
186  }
187 
188  return WEXITSTATUS(status);
189  }
190 
191  /*
192  * We don't close fd's 0, 1, and 2. If we're in debugging mode,
193  * then they should go to stdout (etc), along with the other
194  * server log messages.
195  *
196  * If we're not in debugging mode, then the code in radiusd.c
197  * takes care of connecting fd's 0, 1, and 2 to /dev/null.
198  */
199  closefrom(3);
200 
201  inet_ntop(ipaddr.af, &ipaddr.ipaddr, buffer, sizeof(buffer));
202  snprintf(port, 11, "%u", nas_port);
203 
204 #ifdef __EMX__
205  /* OS/2 can't directly execute scripts then we call the command
206  processor to execute checkrad
207  */
208  execl(getenv("COMSPEC"), "", "/C","checkrad", cl->nas_type, buffer, port,
209  user, session_id, NULL);
210 #else
211  execl(main_config.checkrad, "checkrad", cl->nas_type, buffer, port,
212  user, session_id, NULL);
213 #endif
214  ERROR("Check-TS: exec %s: %s", main_config.checkrad, fr_syserror(errno));
215 
216  /*
217  * Exit - 2 means "some error occured".
218  */
219  exit(2);
220 }
221 #else
222 int rad_check_ts(UNUSED uint32_t nasaddr, UNUSED unsigned int nas_port,
223  UNUSED char const *user, UNUSED char const *session_id)
224 {
225  ERROR("Simultaneous-Use is not supported");
226  return 2;
227 }
228 #endif
229 
230 #else
231 /* WITH_SESSION_MGMT */
232 
233 int session_zap(UNUSED REQUEST *request, UNUSED uint32_t nasaddr, UNUSED uint32_t nas_port,
234  UNUSED char const *user,
235  UNUSED char const *sessionid, UNUSED uint32_t cliaddr, UNUSED char proto,
236  UNUSED int session_time)
237 {
238  return RLM_MODULE_FAIL;
239 }
240 
241 int rad_check_ts(UNUSED uint32_t nasaddr, UNUSED unsigned int nas_port,
242  UNUSED char const *user, UNUSED char const *session_id)
243 {
244  ERROR("Simultaneous-Use is not supported");
245  return 2;
246 }
247 #endif
#define PW_PPP
Definition: radius.h:186
#define PW_SLIP
Definition: radius.h:187
Main server configuration.
Definition: radiusd.h:108
char const * nas_type
Type of client (arbitrary).
Definition: clients.h:47
int session_zap(REQUEST *request, uint32_t nasaddr, uint32_t nas_port, char const *user, char const *sessionid, uint32_t cliaddr, char proto, int session_time)
Definition: session.c:37
int rad_accounting(REQUEST *)
Definition: acct.c:38
#define STRINGPAIR(n, v)
#define INTPAIR(n, v)
int closefrom(int fd)
Definition: misc.c:378
#define WEXITSTATUS(stat_val)
Definition: exec.c:40
VALUE_PAIR * username
Cached username VALUE_PAIR from request RADIUS_PACKET.
Definition: radiusd.h:222
#define UNUSED
Definition: libradius.h:134
#define PW_FRAMED_USER
Definition: radius.h:174
char const * inet_ntop(int af, void const *src, char *dst, size_t cnt)
Definition: missing.c:538
PUBLIC int snprintf(char *string, size_t length, char *format, va_alist)
Definition: snprintf.c:686
VALUE_PAIR * password
Cached password VALUE_PAIR from request RADIUS_PACKET.
Definition: radiusd.h:223
rad_listen_t * listener
The listener that received the request.
Definition: radiusd.h:218
#define rad_waitpid(a, b)
Definition: radiusd.h:564
int rad_check_ts(uint32_t nasaddr, uint32_t nas_port, char const *user, char const *session_id)
Definition: session.c:126
#define IPPAIR(n, v)
REQUEST * request_alloc_fake(REQUEST *oldreq)
Definition: request.c:124
#define rad_fork(n)
Definition: radiusd.h:563
static char const * proto
Definition: radclient.c:63
int af
Address family.
Definition: inet.h:42
#define rad_assert(expr)
Definition: rad_assert.h:38
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
Definition: log.c:238
#define DEBUG2(fmt,...)
Definition: log.h:176
RFC2866 - Accounting-Request.
Definition: radius.h:95
union fr_ipaddr_t::@1 ipaddr
unsigned int code
Packet code (type).
Definition: libradius.h:155
Stores an attribute, a value and various bits of other data.
Definition: pair.h:112
RADCLIENT * client_find_old(fr_ipaddr_t const *ipaddr)
Definition: client.c:472
Describes a host allowed to send packets to the server.
Definition: clients.h:35
char const * checkrad
Script to use to determine if a user is already connected.
Definition: radiusd.h:144
Module failed, don't reply.
Definition: radiusd.h:90
RADIUS_PACKET * packet
Incoming request.
Definition: radiusd.h:221
#define PW_STATUS_STOP
Definition: radius.h:192
IPv4/6 prefix.
Definition: inet.h:41
#define RCSID(id)
Definition: build.h:135
#define ERROR(fmt,...)
Definition: log.h:145
#define PW_LOGIN_USER
Definition: radius.h:173