]> git.stg.codes - stg.git/blob - projects/rlm_stg/stg_client.cpp
Очередная проверка post-commit hook
[stg.git] / projects / rlm_stg / stg_client.cpp
1 /*
2  *    This program is free software; you can redistribute it and/or modify
3  *    it under the terms of the GNU General Public License as published by
4  *    the Free Software Foundation; either version 2 of the License, or
5  *    (at your option) any later version.
6  *
7  *    This program is distributed in the hope that it will be useful,
8  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
9  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  *    GNU General Public License for more details.
11  *
12  *    You should have received a copy of the GNU General Public License
13  *    along with this program; if not, write to the Free Software
14  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
15  */
16
17 /*
18  *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
19  */
20
21 /*
22  *  Realization of data access via Stargazer for RADIUS
23  *
24  *  $Revision: 1.8 $
25  *  $Date: 2010/04/16 12:30:02 $
26  *
27  */
28
29 #include <netdb.h>
30 #include <sys/types.h>
31 #include <unistd.h> // close
32 #include <cstring>
33
34 #include "stg_client.h"
35
36 using namespace std;
37
38 //-----------------------------------------------------------------------------
39 //-----------------------------------------------------------------------------
40 //-----------------------------------------------------------------------------
41 STG_CLIENT::STG_CLIENT()
42     : port(0),
43       localPort(0),
44       sock(0)
45 {
46 }
47 //-----------------------------------------------------------------------------
48 STG_CLIENT::~STG_CLIENT()
49 {
50 }
51 //-----------------------------------------------------------------------------
52 void STG_CLIENT::SetServer(const string & host)
53 {
54 STG_CLIENT::host = host;
55 }
56 //-----------------------------------------------------------------------------
57 void STG_CLIENT::SetPort(uint16_t port)
58 {
59 STG_CLIENT::port = port;
60 }
61 //-----------------------------------------------------------------------------
62 void STG_CLIENT::SetLocalPort(uint16_t port)
63 {
64 STG_CLIENT::localPort = port;
65 }
66 //-----------------------------------------------------------------------------
67 void STG_CLIENT::SetPassword(const string & password)
68 {
69 STG_CLIENT::password = password;
70 }
71 //-----------------------------------------------------------------------------
72 uint32_t STG_CLIENT::GetFramedIP() const
73 {
74 return framedIP;
75 }
76 //-----------------------------------------------------------------------------
77 void STG_CLIENT::InitEncrypt()
78 {
79 unsigned char keyL[RAD_PASSWORD_LEN];
80 memset(keyL, 0, RAD_PASSWORD_LEN);
81 strncpy((char *)keyL, password.c_str(), RAD_PASSWORD_LEN);
82 Blowfish_Init(&ctx, keyL, RAD_PASSWORD_LEN);
83 }
84 //-----------------------------------------------------------------------------
85 int STG_CLIENT::PrepareNet()
86 {
87 sock = socket(AF_INET, SOCK_DGRAM, 0);
88 if (sock == -1)
89     {
90     errorStr = "Socket create error";
91     return -1;
92     }
93
94 struct hostent * he = NULL;
95 he = gethostbyname(host.c_str());
96 if (he == NULL)
97     {
98     errorStr = "gethostbyname error";
99     return -1;
100     }
101
102 if (localPort != 0)
103     {
104     struct sockaddr_in localAddr;
105     localAddr.sin_family = AF_INET;
106     localAddr.sin_port = htons(localPort);
107     localAddr.sin_addr.s_addr = inet_addr("0.0.0.0");;
108
109     if (bind(sock, (struct sockaddr *)&localAddr, sizeof(localAddr)))
110         {
111         errorStr = "Bind failed";
112         return -1;
113         }
114     }
115
116 outerAddr.sin_family = AF_INET;
117 outerAddr.sin_port = htons(port);
118 outerAddr.sin_addr.s_addr = *(uint32_t *)he->h_addr;
119
120 outerAddrLen = sizeof(struct sockaddr_in);
121
122 return 0;
123 }
124 //-----------------------------------------------------------------------------
125 void STG_CLIENT::FinalizeNet()
126 {
127 close(sock);
128 }
129 //-----------------------------------------------------------------------------
130 int STG_CLIENT::Start()
131 {
132 InitEncrypt();
133
134 return PrepareNet();
135 }
136 //-----------------------------------------------------------------------------
137 int STG_CLIENT::Stop()
138 {
139 FinalizeNet();
140
141 return 0;
142 }
143 //-----------------------------------------------------------------------------
144 string STG_CLIENT::GetUserPassword() const
145 {
146 return userPassword;
147 }
148 //-----------------------------------------------------------------------------
149 int STG_CLIENT::Send(const RAD_PACKET & packet)
150 {
151 char buf[RAD_MAX_PACKET_LEN];
152     
153 Encrypt(buf, (char *)&packet, sizeof(RAD_PACKET) / 8);
154
155 int res = sendto(sock, buf, sizeof(RAD_PACKET), 0, (struct sockaddr *)&outerAddr, outerAddrLen);
156
157 if (res == -1)
158     errorStr = "Error sending data";
159
160 return res;
161 }
162 //-----------------------------------------------------------------------------
163 int STG_CLIENT::RecvData(RAD_PACKET * packet)
164 {
165 char buf[RAD_MAX_PACKET_LEN];
166 int res;
167
168 outerAddrLen = sizeof(struct sockaddr_in);
169
170 res = recvfrom(sock, buf, RAD_MAX_PACKET_LEN, 0, (struct sockaddr *)&outerAddr, &outerAddrLen);
171 if (res == -1)
172     {
173     errorStr = "Error receiving data";
174     return -1;
175     }
176
177 Decrypt((char *)packet, buf, res / 8);
178
179 return 0;
180 }
181 //-----------------------------------------------------------------------------
182 int STG_CLIENT::Request(RAD_PACKET * packet, const std::string & login, const std::string & svc, uint8_t packetType)
183 {
184 int res;
185
186 memcpy((void *)&packet->magic, (void *)RAD_ID, RAD_MAGIC_LEN);
187 packet->protoVer[0] = '0';
188 packet->protoVer[1] = '1';
189 packet->packetType = packetType;
190 packet->ip = 0;
191 strncpy((char *)packet->login, login.c_str(), RAD_LOGIN_LEN);
192 strncpy((char *)packet->service, svc.c_str(), RAD_SERVICE_LEN);
193
194 res = Send(*packet);
195 if (res == -1)
196     return -1;
197
198 res = RecvData(packet);
199 if (res == -1)
200     return -1;
201
202 if (strncmp((char *)packet->magic, RAD_ID, RAD_MAGIC_LEN))
203     {
204     errorStr = "Magic invalid. Wanted: '";
205     errorStr += RAD_ID;
206     errorStr += "', got: '";
207     errorStr += (char *)packet->magic;
208     errorStr += "'";
209     return -1;
210     }
211
212 return 0;
213 }
214 //-----------------------------------------------------------------------------
215 int STG_CLIENT::Authorize(const string & login, const string & svc)
216 {
217 RAD_PACKET packet;
218
219 userPassword = "";
220
221 if (Request(&packet, login, svc, RAD_AUTZ_PACKET))
222     return -1;
223
224 if (packet.packetType != RAD_ACCEPT_PACKET)
225     return -1;
226
227 userPassword = (char *)packet.password;
228
229 return 0;
230 }
231 //-----------------------------------------------------------------------------
232 int STG_CLIENT::Authenticate(const string & login, const string & svc)
233 {
234 RAD_PACKET packet;
235
236 userPassword = "";
237
238 if (Request(&packet, login, svc, RAD_AUTH_PACKET))
239     return -1;
240
241 if (packet.packetType != RAD_ACCEPT_PACKET)
242     return -1;
243
244 return 0;
245 }
246 //-----------------------------------------------------------------------------
247 int STG_CLIENT::PostAuthenticate(const string & login, const string & svc)
248 {
249 RAD_PACKET packet;
250
251 userPassword = "";
252
253 if (Request(&packet, login, svc, RAD_POST_AUTH_PACKET))
254     return -1;
255
256 if (packet.packetType != RAD_ACCEPT_PACKET)
257     return -1;
258
259 if (svc == "Framed-User")
260     framedIP = packet.ip;
261 else
262     framedIP = 0;
263
264 return 0;
265 }
266 //-----------------------------------------------------------------------------
267 int STG_CLIENT::Account(const std::string & type, const string & login, const string & svc, const string & sessid)
268 {
269 RAD_PACKET packet;
270
271 userPassword = "";
272 strncpy((char *)packet.sessid, sessid.c_str(), RAD_SESSID_LEN);
273
274 if (type == "Start")
275     {
276     if (Request(&packet, login, svc, RAD_ACCT_START_PACKET))
277         return -1;
278     }
279 else if (type == "Stop")
280     {
281     if (Request(&packet, login, svc, RAD_ACCT_STOP_PACKET))
282         return -1;
283     }
284 else if (type == "Interim-Update")
285     {
286     if (Request(&packet, login, svc, RAD_ACCT_UPDATE_PACKET))
287         return -1;
288     }
289 else
290     {
291     if (Request(&packet, login, svc, RAD_ACCT_OTHER_PACKET))
292         return -1;
293     }
294
295 if (packet.packetType != RAD_ACCEPT_PACKET)
296     return -1;
297
298 return 0;
299 }
300 //-----------------------------------------------------------------------------
301 void STG_CLIENT::Encrypt(char * dst, const char * src, int len8)         
302 {
303 // len8 - длина в 8-ми байтовых блоках                                                   
304 if (dst != src) 
305     memcpy(dst, src, len8 * 8);                                                          
306     
307 for (int i = 0; i < len8; i++)
308     Blowfish_Encrypt(&ctx, (uint32_t *)(dst + i*8), (uint32_t *)(dst + i*8 + 4));
309 }
310 //-----------------------------------------------------------------------------          
311 void STG_CLIENT::Decrypt(char * dst, const char * src, int len8)
312 {
313 // len8 - длина в 8-ми байтовых блоках
314 if (dst != src)
315     memcpy(dst, src, len8 * 8);
316
317 for (int i = 0; i < len8; i++)
318     Blowfish_Decrypt(&ctx, (uint32_t *)(dst + i*8), (uint32_t *)(dst + i*8 + 4));
319 }
320 //-----------------------------------------------------------------------------