File: TACACS.cpp

package info (click to toggle)
xmail 1.22-5
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k
  • size: 2,840 kB
  • ctags: 3,857
  • sloc: cpp: 33,585; sh: 625; makefile: 102; perl: 56; sql: 31
file content (284 lines) | stat: -rw-r--r-- 8,955 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
/*
 *  XMail by Davide Libenzi ( Intranet and Internet mail server )
 *  Copyright (C) 1999,..,2004  Davide Libenzi
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 *  Davide Libenzi <davidel@xmailserver.org>
 *
 */

#include "SysInclude.h"
#include "SysDep.h"
#include "SvrDefines.h"
#include "ShBlocks.h"
#include "StrUtils.h"
#include "SList.h"
#include "MailConfig.h"
#include "MailSvr.h"
#include "MiscUtils.h"
#include "TACACS.h"

/*

#define ERR_TACACS_AUTH_FAILED      (-???)
#define ERR_TACACS_AUTH_UNAVAILABLE (-???)
#define ERR_TACACS_FILE_NOT_FOUND   (-???)
#define ERR_TACACS_SERVER_NOT_FOUND (-???)

{ERR_TACACS_AUTH_FAILED, "TACACS authentication failed", NULL},
{ERR_TACACS_AUTH_UNAVAILABLE, "TACACS authentication server unavailable", NULL},
{ERR_TACACS_FILE_NOT_FOUND, "TACACS configuration file not found", NULL},
{ERR_TACACS_SERVER_NOT_FOUND, "TACACS server for domain not found", NULL},

    */

#define TACACS_TIMEOUT          15
#define TACACS_SEND_RETRIES     3
#define TACACS_DPORT            110
#define TACACS_LPORT            0

#define TACS_CONFIG_FILE        "tacacsservers.tab"
#define TACS_ALIAS_LINE_MAX     1024

#define	TACACS_SVC_NAME         "tacacs"
#define	TACACS_PORT             49
#define XTA_VERSION             0x80

#define	TA_QUERY                1
#define	TA_ANSWER               2
#define	TA_CHANGE               3
#define	TA_FOLLOW               4

#define	TA_A_ACCEPTED           1
#define	TA_A_REJECTED           2

#define TA_A_NONE               0
#define	TA_A_EXPIRING           1
#define	TA_A_PASSWORD           2
#define	TA_A_DENIED             3
#define	TA_A_NOROUTE            8	/* Dialup routing not allowed           */
#define	TA_A_LOGINREQ           9	/* Login required for requested action  */

#define XTACACSSIZE             sizeof(xtacacstype)

#define	XTA_LOGIN               1
#define	XTA_ANSWER              2
#define	XTA_CHANGE              3
#define	XTA_FOLLOW              4
#define XTA_CONNECT             5
#define XTA_ENABLE              6
#define XTA_LOGOUT              7
#define XTA_RELOAD              8
#define XTA_SLIPON              9
#define XTA_SLIPOFF             10
#define XTA_SLIPADDR            11
#define XTA_ARAP_AUTH           12
#define XTA_CHAP_AUTH           13

#define	XTA_A_ACCEPTED          1
#define	XTA_A_REJECTED          2

#define XTA_A_NONE              0
#define	XTA_A_EXPIRING          1	/* Account expiring                     */
#define	XTA_A_PASSWORD          2	/* Wrong password                       */
#define	XTA_A_DENIED            3	/* Permission denied                    */
#define	XTA_A_NOROUTE           8	/* Dialup routing not permitted         */
#define	XTA_A_LOGINREQ          9	/* Login required for requested action  */

enum TacsFields {
	tacsDomain = 0,
	tacsServer,
	tacsPort,

	tacsMax
};

struct xtacacstype {
	SYS_UINT8 version;	/* version of protocol      */
	SYS_UINT8 type;		/* Type of query/response   */
	SYS_UINT16 trans;	/* transaction ID           */
	SYS_UINT8 namelen;	/* length of name           */
	SYS_UINT8 pwlen;	/* length of password       */
	SYS_UINT8 response;	/* response code            */
	SYS_UINT8 reason;	/* reason for response      */
	SYS_UINT32 uuid;	/* user id code assigned    */
	SYS_UINT32 dhost;	/* destination host         */
	SYS_UINT16 dport;	/* destination port         */
	SYS_UINT16 lport;	/* local line number        */
	SYS_UINT32 flags;	/* misc flags               */
	SYS_UINT16 accesslist;	/* access list for user     */
/*                  user name[]                             */
/*                  password[]                              */
};

static char *TacsGetConfigFilePath(char *pszTacsFile);
static int TacsGetServerName(char const *pszDomain, char *pszTacsServer, int &iPortNo);

static char *TacsGetConfigFilePath(char *pszTacsFile)
{

	CfgGetRootPath(pszTacsFile);

	strcat(pszTacsFile, TACS_CONFIG_FILE);

	return (pszTacsFile);

}

static int TacsGetServerName(char const *pszDomain, char *pszTacsServer, int &iPortNo)
{

	char szTacsFile[SYS_MAX_PATH] = "";

	TacsGetConfigFilePath(szTacsFile);

	FILE *pTacsFile = fopen(szTacsFile, "rt");

	if (pTacsFile == NULL) {
		ErrSetErrorCode(ERR_TACACS_FILE_NOT_FOUND);
		return (ERR_TACACS_FILE_NOT_FOUND);
	}

	char szTacsLine[TACS_ALIAS_LINE_MAX] = "";

	while (MscGetConfigLine(szTacsLine, sizeof(szTacsLine) - 1, pTacsFile) != NULL) {
		char **ppszStrings = StrGetTabLineStrings(szTacsLine);

		if (ppszStrings == NULL)
			continue;

		int iFieldsCount = StrStringsCount(ppszStrings);

		if ((iFieldsCount >= tacsMax) &&
		    StrIWildMatch(pszDomain, ppszStrings[tacsDomain])) {
			strcpy(pszTacsServer, ppszStrings[tacsServer]);

			iPortNo = atoi(ppszStrings[tacsPort]);

			StrFreeStrings(ppszStrings);
			fclose(pTacsFile);

			return (0);
		}

		StrFreeStrings(ppszStrings);
	}

	fclose(pTacsFile);

	ErrSetErrorCode(ERR_TACACS_SERVER_NOT_FOUND);

	return (ERR_TACACS_SERVER_NOT_FOUND);

}

int TacsAuthenticate(char const *pszDomain, char const *pszUsername,
		     char const *pszPassword, int iServicePort)
{
///////////////////////////////////////////////////////////////////////////////
//  Get TACACS server coordinates
///////////////////////////////////////////////////////////////////////////////
	int iPortNo = TACACS_PORT;
	char szTacsServer[MAX_HOST_NAME] = "";

	if (TacsGetServerName(pszDomain, szTacsServer, iPortNo) < 0)
		return (ErrGetErrorCode());

///////////////////////////////////////////////////////////////////////////////
//  If not specified use POP3 port ( TACACS_DPORT )
///////////////////////////////////////////////////////////////////////////////
	if (iServicePort < 0)
		iServicePort = TACACS_DPORT;

///////////////////////////////////////////////////////////////////////////////
//  Open TACACS server socket
///////////////////////////////////////////////////////////////////////////////
	SYS_SOCKET SockFD;
	SYS_INET_ADDR SvrAddr;
	SYS_INET_ADDR SockAddr;

	if (MscCreateClientSocket(szTacsServer, iPortNo, SOCK_DGRAM, &SockFD, &SvrAddr,
				  &SockAddr, TACACS_TIMEOUT) < 0)
		return (ErrGetErrorCode());

///////////////////////////////////////////////////////////////////////////////
//  Build TACACS request packet
///////////////////////////////////////////////////////////////////////////////
	char szBuffer[1024] = "";
	xtacacstype *pTacs = (xtacacstype *) szBuffer;

	ZeroData(szBuffer);

	pTacs->type = XTA_LOGIN;
	pTacs->version = XTA_VERSION;
	pTacs->trans = htons((unsigned short) SysGetCurrentThreadId());
	pTacs->reason = XTA_A_NONE;
	pTacs->dhost = (SYS_UINT32) SysGetAddrAddress(SockAddr);
	pTacs->dport = htons((unsigned short) iServicePort);
	pTacs->lport = htons(TACACS_LPORT);
	pTacs->namelen = (SYS_UINT8) strlen(pszUsername);
	pTacs->pwlen = (SYS_UINT8) strlen(pszPassword);

	int iQueryLenght = XTACACSSIZE + pTacs->namelen + pTacs->pwlen;

	memcpy(&szBuffer[XTACACSSIZE], pszUsername, pTacs->namelen);
	memcpy(&szBuffer[XTACACSSIZE + pTacs->namelen], pszPassword, pTacs->pwlen);

	for (int iSendLoops = 0; iSendLoops < TACACS_SEND_RETRIES; iSendLoops++) {
///////////////////////////////////////////////////////////////////////////////
//  Send packet
///////////////////////////////////////////////////////////////////////////////
		if (SysSendDataTo(SockFD, (const struct sockaddr *) &SvrAddr, sizeof(SvrAddr),
				  szBuffer, iQueryLenght, TACACS_TIMEOUT) != iQueryLenght)
			continue;

///////////////////////////////////////////////////////////////////////////////
//  Receive packet lenght
///////////////////////////////////////////////////////////////////////////////
		SYS_INET_ADDR RecvAddr;
		SYS_UINT8 RespBuffer[1024];

		ZeroData(RecvAddr);
		ZeroData(RespBuffer);

		int iPacketLenght =
		    SysRecvDataFrom(SockFD, (struct sockaddr *) &RecvAddr, sizeof(RecvAddr),
				    (char *) RespBuffer, sizeof(RespBuffer), TACACS_TIMEOUT);

		if (iPacketLenght < XTACACSSIZE)
			continue;

		xtacacstype *pRespTacs = (xtacacstype *) RespBuffer;

		if (pRespTacs->response != 1) {
			SysCloseSocket(SockFD);

			ErrSetErrorCode(ERR_TACACS_AUTH_FAILED);
			return (ERR_TACACS_AUTH_FAILED);
		}

		SysCloseSocket(SockFD);

		return (0);
	}

	SysCloseSocket(SockFD);

	ErrSetErrorCode(ERR_TACACS_AUTH_UNAVAILABLE);

	return (ERR_TACACS_AUTH_UNAVAILABLE);

}