Ver código fonte

Merge pull request #133 from yehorov/master

Add the possibility to send the Virtual Hub Name to an external DHCP server
Daiyuu Nobori 9 anos atrás
pai
commit
5f8ce287c3

+ 4 - 0
src/Cedar/Hub.c

@@ -700,6 +700,8 @@ void DataToHubOptionStruct(HUB_OPTION *o, RPC_ADMIN_OPTION *ao)
 	GetHubAdminOptionDataAndSet(ao, "SecureNAT_RandomizeAssignIp", &o->SecureNAT_RandomizeAssignIp);
 	GetHubAdminOptionDataAndSet(ao, "DetectDormantSessionInterval", &o->DetectDormantSessionInterval);
 	GetHubAdminOptionDataAndSet(ao, "NoPhysicalIPOnPacketLog", &o->NoPhysicalIPOnPacketLog);
+	GetHubAdminOptionDataAndSet(ao, "UseHubNameAsDhcpUserClassOption", &o->UseHubNameAsDhcpUserClassOption);
+	GetHubAdminOptionDataAndSet(ao, "UseHubNameAsRadiusNasId", &o->UseHubNameAsRadiusNasId);
 }
 
 // Convert the contents of the HUB_OPTION to data
@@ -771,6 +773,8 @@ void HubOptionStructToData(RPC_ADMIN_OPTION *ao, HUB_OPTION *o, char *hub_name)
 	Add(aol, NewAdminOption("SecureNAT_RandomizeAssignIp", o->SecureNAT_RandomizeAssignIp));
 	Add(aol, NewAdminOption("DetectDormantSessionInterval", o->DetectDormantSessionInterval));
 	Add(aol, NewAdminOption("NoPhysicalIPOnPacketLog", o->NoPhysicalIPOnPacketLog));
+	Add(aol, NewAdminOption("UseHubNameAsDhcpUserClassOption", o->UseHubNameAsDhcpUserClassOption));
+	Add(aol, NewAdminOption("UseHubNameAsRadiusNasId", o->UseHubNameAsRadiusNasId));
 
 	Zero(ao, sizeof(RPC_ADMIN_OPTION));
 

+ 2 - 0
src/Cedar/Hub.h

@@ -281,6 +281,8 @@ struct HUB_OPTION
 	bool SecureNAT_RandomizeAssignIp;	// Randomize the assignment IP address for new DHCP client
 	UINT DetectDormantSessionInterval;	// Interval (seconds) threshold to detect a dormant VPN session
 	bool NoPhysicalIPOnPacketLog;		// Disable saving physical IP address on the packet log
+	bool UseHubNameAsDhcpUserClassOption;	// Add HubName to DHCP request as User-Class option
+	bool UseHubNameAsRadiusNasId;		// Add HubName to Radius request as NAS-Identifier attrioption
 };
 
 // MAC table entry

+ 29 - 0
src/Cedar/IPsec_IPC.c

@@ -679,6 +679,24 @@ void FreeIPC(IPC *ipc)
 	Free(ipc);
 }
 
+// Set User Class option if corresponding Virtual Hub optin is set
+void IPCDhcpSetConditionalUserClass(IPC *ipc, DHCP_OPTION_LIST *req)
+{
+	HUB *hub;
+
+	hub = GetHub(ipc->Cedar, ipc->HubName);
+	if (hub == NULL)
+	{
+		return;
+	}
+
+	if (hub->Option && hub->Option->UseHubNameAsDhcpUserClassOption == true)
+	{
+		StrCpy(req->UserClass, sizeof(req->UserClass), ipc->HubName);
+	}
+	ReleaseHub(hub);
+}
+
 // Release the IP address from the DHCP server
 void IPCDhcpFreeIP(IPC *ipc, IP *dhcp_server)
 {
@@ -693,6 +711,7 @@ void IPCDhcpFreeIP(IPC *ipc, IP *dhcp_server)
 	Zero(&req, sizeof(req));
 	req.Opcode = DHCP_RELEASE;
 	req.ServerAddress = IPToUINT(dhcp_server);
+	IPCDhcpSetConditionalUserClass(ipc, &req);
 
 	FreeDHCPv4Data(IPCSendDhcpRequest(ipc, NULL, tran_id, &req, 0, 0, NULL));
 }
@@ -713,6 +732,7 @@ void IPCDhcpRenewIP(IPC *ipc, IP *dhcp_server)
 	req.Opcode = DHCP_REQUEST;
 	StrCpy(req.Hostname, sizeof(req.Hostname), ipc->ClientHostname);
 	req.RequestedIp = IPToUINT(&ipc->ClientIPAddress);
+	IPCDhcpSetConditionalUserClass(ipc, &req);
 
 	FreeDHCPv4Data(IPCSendDhcpRequest(ipc, dhcp_server, tran_id, &req, 0, 0, NULL));
 }
@@ -735,6 +755,7 @@ bool IPCDhcpRequestInformIP(IPC *ipc, DHCP_OPTION_LIST *opt, TUBE *discon_poll_t
 	req.Opcode = DHCP_INFORM;
 	req.ClientAddress = IPToUINT(client_ip);
 	StrCpy(req.Hostname, sizeof(req.Hostname), ipc->ClientHostname);
+	IPCDhcpSetConditionalUserClass(ipc, &req);
 
 	d = IPCSendDhcpRequest(ipc, NULL, tran_id, &req, DHCP_ACK, IPC_DHCP_TIMEOUT, discon_poll_tube);
 	if (d == NULL)
@@ -799,6 +820,7 @@ LABEL_RETRY_FOR_OPENVPN:
 	req.RequestedIp = request_ip;
 	req.Opcode = DHCP_DISCOVER;
 	StrCpy(req.Hostname, sizeof(req.Hostname), ipc->ClientHostname);
+	IPCDhcpSetConditionalUserClass(ipc, &req);
 
 	d = IPCSendDhcpRequest(ipc, NULL, tran_id, &req, DHCP_OFFER, IPC_DHCP_TIMEOUT, discon_poll_tube);
 	if (d == NULL)
@@ -909,6 +931,7 @@ LABEL_RETRY_FOR_OPENVPN:
 	StrCpy(req.Hostname, sizeof(req.Hostname), ipc->ClientHostname);
 	req.ServerAddress = d->ParsedOptionList->ServerAddress;
 	req.RequestedIp = d->ParsedOptionList->ClientAddress;
+	IPCDhcpSetConditionalUserClass(ipc, &req);
 
 	d2 = IPCSendDhcpRequest(ipc, NULL, tran_id, &req, DHCP_ACK, IPC_DHCP_TIMEOUT, discon_poll_tube);
 	if (d2 == NULL)
@@ -1243,6 +1266,12 @@ BUF *IPCBuildDhcpRequestOptions(IPC *ipc, DHCP_OPTION_LIST *opt)
 		Add(o, NewDhcpOption(DHCP_ID_HOST_NAME, opt->Hostname, StrLen(opt->Hostname)));
 	}
 
+	// User Class
+	if (IsEmptyStr(opt->UserClass) == false)
+	{
+		Add(o, NewDhcpOption(DHCP_ID_USER_CLASS, opt->UserClass, StrLen(opt->UserClass)));
+	}
+
 	// Vendor
 	Add(o, NewDhcpOption(DHCP_ID_VENDOR_ID, IPC_DHCP_VENDOR_ID, StrLen(IPC_DHCP_VENDOR_ID)));
 

+ 4 - 0
src/Cedar/Protocol.c

@@ -1655,6 +1655,10 @@ bool ServerAccept(CONNECTION *c)
 			{
 				radius_login_opt.In_CheckVLanId = hub->Option->AssignVLanIdByRadiusAttribute;
 				radius_login_opt.In_DenyNoVlanId = hub->Option->DenyAllRadiusLoginWithNoVlanAssign;
+				if (hub->Option->UseHubNameAsRadiusNasId == true)
+				{
+					StrCpy(radius_login_opt.NasId, sizeof(radius_login_opt.NasId), hubname);
+				}
 			}
 
 			// Get the various flags

+ 10 - 1
src/Cedar/Radius.c

@@ -1833,7 +1833,16 @@ bool RadiusLogin(CONNECTION *c, char *hubname, char *server, UINT port, UCHAR *s
 	{
 		// Generate a password packet
 		BUF *user_password = (is_mschap ? NULL : RadiusCreateUserPassword(encrypted_password->Buf, encrypted_password->Size));
-		BUF *nas_id = RadiusCreateNasId(CEDAR_SERVER_STR);
+		BUF *nas_id;
+
+		if (IsEmptyStr(opt->NasId) == true)
+		{
+			nas_id = RadiusCreateNasId(CEDAR_SERVER_STR);
+		}
+		else
+		{
+			nas_id = RadiusCreateNasId(opt->NasId);
+		}
 
 		if (is_mschap || user_password != NULL)
 		{

+ 2 - 0
src/Cedar/Radius.h

@@ -142,6 +142,7 @@
 #define	RADIUS_ATTRIBUTE_EAP_MESSAGE				79
 #define	RADIUS_ATTRIBUTE_EAP_AUTHENTICATOR			80
 #define	RADIUS_ATTRIBUTE_VLAN_ID					81
+#define	RADIUS_MAX_NAS_ID_LEN						253
 
 // RADIUS codes
 #define	RADIUS_CODE_ACCESS_REQUEST					1
@@ -371,6 +372,7 @@ struct RADIUS_LOGIN_OPTION
 	bool In_DenyNoVlanId;
 	UINT Out_VLanId;
 	bool Out_IsRadiusLogin;
+	char NasId[RADIUS_MAX_NAS_ID_LEN + 1];	// NAS-Identifier
 };
 
 // Function prototype

+ 8 - 0
src/Cedar/Server.c

@@ -4114,6 +4114,8 @@ void SiLoadHubOptionCfg(FOLDER *f, HUB_OPTION *o)
 	o->SecureNAT_RandomizeAssignIp = CfgGetBool(f, "SecureNAT_RandomizeAssignIp");
 	o->DetectDormantSessionInterval = CfgGetInt(f, "DetectDormantSessionInterval");
 	o->NoPhysicalIPOnPacketLog = CfgGetBool(f, "NoPhysicalIPOnPacketLog");
+	o->UseHubNameAsDhcpUserClassOption = CfgGetBool(f, "UseHubNameAsDhcpUserClassOption");
+	o->UseHubNameAsRadiusNasId = CfgGetBool(f, "UseHubNameAsRadiusNasId");
 
 	// Enabled by default
 	if (CfgIsItem(f, "ManageOnlyPrivateIP"))
@@ -4214,6 +4216,8 @@ void SiWriteHubOptionCfg(FOLDER *f, HUB_OPTION *o)
 	CfgAddBool(f, "DisableUserModeSecureNAT", o->DisableUserModeSecureNAT);
 	CfgAddBool(f, "DisableCheckMacOnLocalBridge", o->DisableCheckMacOnLocalBridge);
 	CfgAddBool(f, "DisableCorrectIpOffloadChecksum", o->DisableCorrectIpOffloadChecksum);
+	CfgAddBool(f, "UseHubNameAsDhcpUserClassOption", o->UseHubNameAsDhcpUserClassOption);
+	CfgAddBool(f, "UseHubNameAsRadiusNasId", o->UseHubNameAsRadiusNasId);
 }
 
 // Write the user
@@ -7625,6 +7629,8 @@ void SiCalledUpdateHub(SERVER *s, PACK *p)
 	o.DisableUserModeSecureNAT = PackGetBool(p, "DisableUserModeSecureNAT");
 	o.DisableCheckMacOnLocalBridge = PackGetBool(p, "DisableCheckMacOnLocalBridge");
 	o.DisableCorrectIpOffloadChecksum = PackGetBool(p, "DisableCorrectIpOffloadChecksum");
+	o.UseHubNameAsDhcpUserClassOption = PackGetBool(p, "UseHubNameAsDhcpUserClassOption");
+	o.UseHubNameAsRadiusNasId = PackGetBool(p, "UseHubNameAsRadiusNasId");
 
 	save_packet_log = PackGetInt(p, "SavePacketLog");
 	packet_log_switch_type = PackGetInt(p, "PacketLogSwitchType");
@@ -9477,6 +9483,8 @@ void SiPackAddCreateHub(PACK *p, HUB *h)
 	PackAddInt(p, "SecurityLogSwitchType", h->LogSetting.SecurityLogSwitchType);
 	PackAddData(p, "HashedPassword", h->HashedPassword, SHA1_SIZE);
 	PackAddData(p, "SecurePassword", h->SecurePassword, SHA1_SIZE);
+	PackAddBool(p, "UseHubNameAsDhcpUserClassOption", h->Option->UseHubNameAsDhcpUserClassOption);
+	PackAddBool(p, "UseHubNameAsRadiusNasId", h->Option->UseHubNameAsRadiusNasId);
 
 	SiAccessListToPack(p, h->AccessList);
 

+ 7 - 0
src/Mayaqua/TcpIp.h

@@ -623,6 +623,7 @@ struct ICMPV6_HEADER_INFO
 #define	DHCP_ID_CLIENT_ID			0x3d
 #define	DHCP_ID_VENDOR_ID			0x3c
 #define	DHCP_ID_REQ_PARAM_LIST		0x37
+#define	DHCP_ID_USER_CLASS			0x4d
 #define	DHCP_ID_CLASSLESS_ROUTE		0x79
 #define	DHCP_ID_MS_CLASSLESS_ROUTE	0xF9
 #define	DHCP_ID_PRIVATE				0xFA
@@ -794,6 +795,8 @@ struct DHCP_CLASSLESS_ROUTE_TABLE
 	DHCP_CLASSLESS_ROUTE Entries[MAX_DHCP_CLASSLESS_ROUTE_ENTRIES];	// Entries
 };
 
+#define	MAX_USER_CLASS_LEN	255
+
 // DHCP option list
 struct DHCP_OPTION_LIST
 {
@@ -803,6 +806,10 @@ struct DHCP_OPTION_LIST
 	// Client request
 	UINT RequestedIp;				// Requested IP address
 	char Hostname[MAX_HOST_NAME_LEN + 1]; // Host name
+	char UserClass[MAX_USER_CLASS_LEN + 1]; // User class
+	// RFC3003 defines that User Class option is array of text strings,
+	// but the most popular DHCP clients and servers,
+	// i.e. ISC DHCP and Microsoft DHCP Server, consider it a text string
 
 	// Server response
 	UINT ClientAddress;				// Client address

+ 2 - 0
src/bin/hamcore/strtable_en.stb

@@ -557,6 +557,8 @@ HUB_AO_DenyAllRadiusLoginWithNoVlanAssign	If you set this option to non-zero val
 HUB_AO_SecureNAT_RandomizeAssignIp			If you set this option to non-zero value, then the Virtual DHCP Server of the SecureNAT function will choose an unused IP address randomly from the DHCP pool while the default behavior is to choose the first unused IP address.
 HUB_AO_DetectDormantSessionInterval			If you set this option to non-zero value, then the Virtual Hub will treat the VPN sessions, which have transmitted no packets for the last specified intervals (in seconds), as Dormant Sessions. The Virtual Hub will not flood packets, which should be flood, to any Dormant Sessions.
 HUB_AO_NoPhysicalIPOnPacketLog				If you set this option to non-zero value, then the physical IP addresses of VPN clients of either the source VPN session or the destination VPN session will not be recorded on the packet log file.
+HUB_AO_UseHubNameAsDhcpUserClassOption		If you set this option to non-zero value, then the Virtual Hub Name will be added to a DHCP request to an external DHCP server as the "User-Class" option. This allows to use separate pools of IP addresses for each Virtual Hub.
+HUB_AO_UseHubNameAsRadiusNasId			If you set this option to non-zero value, then the NAS-Identidier RADIUS attribute will be set to a name of the Virtual Hub. This allows to determine on Radius server whether access to the Virtual Hub should be granted or denied.
 
 
 # Concerning failed connection dialogs