]> git.stg.codes - stg.git/blob - projects/rlm_stg/stg_client.cpp
75d443adfee748a58a4279b78f885308807af6cb
[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
33 #include <cerrno>
34 #include <cstring>
35
36 #include <stdexcept>
37
38 #include "stg_client.h"
39
40 using namespace std;
41
42 //-----------------------------------------------------------------------------
43 //-----------------------------------------------------------------------------
44 //-----------------------------------------------------------------------------
45 STG_CLIENT::STG_CLIENT(const std::string & host, uint16_t port, uint16_t lp, const std::string & pass)
46     : localPort(lp),
47       password(pass),
48       framedIP(0)
49 {
50 sock = socket(AF_INET, SOCK_DGRAM, 0);
51 if (sock == -1)
52     {
53     std::string message = strerror(errno);
54     message = "Socket create error: '" + message + "'";
55     throw std::runtime_error(message);
56     }
57
58 struct hostent * he = NULL;
59 he = gethostbyname(host.c_str());
60 if (he == NULL)
61     {
62     throw std::runtime_error("gethostbyname error");
63     }
64
65 outerAddr.sin_family = AF_INET;
66 outerAddr.sin_port = htons(port);
67 outerAddr.sin_addr.s_addr = *(uint32_t *)he->h_addr;
68
69 InitEncrypt();
70 }
71 //-----------------------------------------------------------------------------
72 STG_CLIENT::~STG_CLIENT()
73 {
74 close(sock);
75 }
76 //-----------------------------------------------------------------------------
77 uint32_t STG_CLIENT::GetFramedIP() const
78 {
79 return framedIP;
80 }
81 //-----------------------------------------------------------------------------
82 inline
83 void STG_CLIENT::InitEncrypt()
84 {
85 unsigned char keyL[RAD_PASSWORD_LEN];
86 memset(keyL, 0, RAD_PASSWORD_LEN);
87 strncpy((char *)keyL, password.c_str(), RAD_PASSWORD_LEN);
88 Blowfish_Init(&ctx, keyL, RAD_PASSWORD_LEN);
89 }
90 //-----------------------------------------------------------------------------
91 int STG_CLIENT::PrepareNet()
92 {
93 if (localPort != 0)
94     {
95     struct sockaddr_in localAddr;
96     localAddr.sin_family = AF_INET;
97     localAddr.sin_port = htons(localPort);
98     localAddr.sin_addr.s_addr = inet_addr("0.0.0.0");;
99
100     if (bind(sock, (struct sockaddr *)&localAddr, sizeof(localAddr)))
101         {
102         errorStr = "Bind failed";
103         return -1;
104         }
105     }
106 return 0;
107 }
108 //-----------------------------------------------------------------------------
109 int STG_CLIENT::Start()
110 {
111 return PrepareNet();
112 }
113 //-----------------------------------------------------------------------------
114 int STG_CLIENT::Stop()
115 {
116 return 0;
117 }
118 //-----------------------------------------------------------------------------
119 string STG_CLIENT::GetUserPassword() const
120 {
121 return userPassword;
122 }
123 //-----------------------------------------------------------------------------
124 int STG_CLIENT::Send(const RAD_PACKET & packet)
125 {
126 char buf[RAD_MAX_PACKET_LEN];
127     
128 Encrypt(buf, (char *)&packet, sizeof(RAD_PACKET) / 8);
129
130 int res = sendto(sock, buf, sizeof(RAD_PACKET), 0, (struct sockaddr *)&outerAddr, sizeof(outerAddr));
131
132 if (res == -1)
133     errorStr = "Error sending data";
134
135 return res;
136 }
137 //-----------------------------------------------------------------------------
138 int STG_CLIENT::RecvData(RAD_PACKET * packet)
139 {
140 char buf[RAD_MAX_PACKET_LEN];
141 int res;
142
143 struct sockaddr_in addr;
144 socklen_t len = sizeof(struct sockaddr_in);
145
146 res = recvfrom(sock, buf, RAD_MAX_PACKET_LEN, 0, reinterpret_cast<struct sockaddr *>(&addr), &len);
147 if (res == -1)
148     {
149     errorStr = "Error receiving data";
150     return -1;
151     }
152
153 Decrypt((char *)packet, buf, res / 8);
154
155 return 0;
156 }
157 //-----------------------------------------------------------------------------
158 int STG_CLIENT::Request(RAD_PACKET * packet, const std::string & login, const std::string & svc, uint8_t packetType)
159 {
160 int res;
161
162 memcpy((void *)&packet->magic, (void *)RAD_ID, RAD_MAGIC_LEN);
163 packet->protoVer[0] = '0';
164 packet->protoVer[1] = '1';
165 packet->packetType = packetType;
166 packet->ip = 0;
167 strncpy((char *)packet->login, login.c_str(), RAD_LOGIN_LEN);
168 strncpy((char *)packet->service, svc.c_str(), RAD_SERVICE_LEN);
169
170 res = Send(*packet);
171 if (res == -1)
172     return -1;
173
174 res = RecvData(packet);
175 if (res == -1)
176     return -1;
177
178 if (strncmp((char *)packet->magic, RAD_ID, RAD_MAGIC_LEN))
179     {
180     errorStr = "Magic invalid. Wanted: '";
181     errorStr += RAD_ID;
182     errorStr += "', got: '";
183     errorStr += (char *)packet->magic;
184     errorStr += "'";
185     return -1;
186     }
187
188 return 0;
189 }
190 //-----------------------------------------------------------------------------
191 int STG_CLIENT::Authorize(const string & login, const string & svc)
192 {
193 RAD_PACKET packet;
194
195 userPassword = "";
196
197 if (Request(&packet, login, svc, RAD_AUTZ_PACKET))
198     return -1;
199
200 if (packet.packetType != RAD_ACCEPT_PACKET)
201     return -1;
202
203 userPassword = (char *)packet.password;
204
205 return 0;
206 }
207 //-----------------------------------------------------------------------------
208 int STG_CLIENT::Authenticate(const string & login, const string & svc)
209 {
210 RAD_PACKET packet;
211
212 userPassword = "";
213
214 if (Request(&packet, login, svc, RAD_AUTH_PACKET))
215     return -1;
216
217 if (packet.packetType != RAD_ACCEPT_PACKET)
218     return -1;
219
220 return 0;
221 }
222 //-----------------------------------------------------------------------------
223 int STG_CLIENT::PostAuthenticate(const string & login, const string & svc)
224 {
225 RAD_PACKET packet;
226
227 userPassword = "";
228
229 if (Request(&packet, login, svc, RAD_POST_AUTH_PACKET))
230     return -1;
231
232 if (packet.packetType != RAD_ACCEPT_PACKET)
233     return -1;
234
235 if (svc == "Framed-User")
236     framedIP = packet.ip;
237 else
238     framedIP = 0;
239
240 return 0;
241 }
242 //-----------------------------------------------------------------------------
243 int STG_CLIENT::Account(const std::string & type, const string & login, const string & svc, const string & sessid)
244 {
245 RAD_PACKET packet;
246
247 userPassword = "";
248 strncpy((char *)packet.sessid, sessid.c_str(), RAD_SESSID_LEN);
249
250 if (type == "Start")
251     {
252     if (Request(&packet, login, svc, RAD_ACCT_START_PACKET))
253         return -1;
254     }
255 else if (type == "Stop")
256     {
257     if (Request(&packet, login, svc, RAD_ACCT_STOP_PACKET))
258         return -1;
259     }
260 else if (type == "Interim-Update")
261     {
262     if (Request(&packet, login, svc, RAD_ACCT_UPDATE_PACKET))
263         return -1;
264     }
265 else
266     {
267     if (Request(&packet, login, svc, RAD_ACCT_OTHER_PACKET))
268         return -1;
269     }
270
271 if (packet.packetType != RAD_ACCEPT_PACKET)
272     return -1;
273
274 return 0;
275 }
276 //-----------------------------------------------------------------------------
277 void STG_CLIENT::Encrypt(char * dst, const char * src, int len8)         
278 {
279 // len8 - длина в 8-ми байтовых блоках                                                   
280 if (dst != src) 
281     memcpy(dst, src, len8 * 8);                                                          
282     
283 for (int i = 0; i < len8; i++)
284     Blowfish_Encrypt(&ctx, (uint32_t *)(dst + i*8), (uint32_t *)(dst + i*8 + 4));
285 }
286 //-----------------------------------------------------------------------------
287 void STG_CLIENT::Decrypt(char * dst, const char * src, int len8)
288 {
289 // len8 - длина в 8-ми байтовых блоках
290 if (dst != src)
291     memcpy(dst, src, len8 * 8);
292
293 for (int i = 0; i < len8; i++)
294     Blowfish_Decrypt(&ctx, (uint32_t *)(dst + i*8), (uint32_t *)(dst + i*8 + 4));
295 }
296 //-----------------------------------------------------------------------------