Skip to content

Commit

Permalink
Merge pull request #1 from liveaverage/master
Browse files Browse the repository at this point in the history
Added support for squiguard username handling when URL requests are submitted via Websense v4 from Cisco ASA using user-identity (Identity Firwall)
  • Loading branch information
jeroennijhof committed Dec 18, 2013
2 parents 1c72631 + 6566743 commit 9ecaba2
Show file tree
Hide file tree
Showing 7 changed files with 179 additions and 27 deletions.
2 changes: 1 addition & 1 deletion n2h2.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ void n2h2_deny(int fd, struct n2h2_req *n2h2_request, char *redirect_url) {
}

struct uf_request n2h2_validate(struct n2h2_req *n2h2_request, int msgsize) {
struct uf_request request = { 0, {0}, {0}, "" };
struct uf_request request = { 0, {0}, {0}, "", "" };
struct in_addr srcip, dstip;
int i;

Expand Down
99 changes: 84 additions & 15 deletions openufp.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ void usage() {
printf("OPTIONS:\n");
printf(" -l PORT on which port openufp will listen for incoming requests\n");
printf(" -r URL when url is denied the client will be redirected to this url; n2h2 only\n");
printf(" -u utilize User Identity info from capable Cisco products. Must use with -w as frontend\n");
printf(" -c SECS cache expire time in seconds; default 3600; 0 disables caching\n");
printf(" -C URL remove specified URL from cache\n");
printf(" -d LEVEL debug level 1-3\n\n");
Expand All @@ -46,14 +47,14 @@ void usage() {
printf("Report bugs to: [email protected]\n\n");
}


// Main function
int main(int argc, char**argv) {
int openufp_fd;
pid_t pid, child_pid;
struct sockaddr_in openufp_addr;
int local_port = 0;
char *redirect_url = NULL;
char sg_redirect[URL_SIZE];
int cache_exp_secs = 3600;
int debug = 0;
int frontend = 0;
Expand All @@ -62,9 +63,12 @@ int main(int argc, char**argv) {
char *proxy_deny_pattern = NULL;
char *blacklist = NULL;
int squidguard = 0;

int usrid = 0;
int c;
while ((c = getopt(argc, argv, "l:r:c:C:d:nwp:f:g")) != -1) {
char *https = "https://";
// bool isIp;

while ((c = getopt(argc, argv, "l:r:c:C:d:nwp:f:gu")) != -1) {
char *p;
char hash[10];
DB *cachedb;
Expand Down Expand Up @@ -116,12 +120,15 @@ int main(int argc, char**argv) {
case 'g':
squidguard = 1;
break;
case 'u':
usrid = 1;
break;
default:
usage();
exit(1);
}
}
if (frontend == 0 || ((proxy_ip == NULL || proxy_port == 0 || proxy_deny_pattern == NULL)
if (frontend == 0 || (frontend != WEBSNS && usrid == 1) || ((proxy_ip == NULL || proxy_port == 0 || proxy_deny_pattern == NULL)
&& blacklist == NULL && squidguard == 0)) {
usage();
exit(1);
Expand Down Expand Up @@ -173,6 +180,11 @@ int main(int argc, char**argv) {
syslog(LOG_INFO, "v%s: Jeroen Nijhof <[email protected]>", VERSION);
syslog(LOG_INFO, "started listening on %d, waiting for requests...", local_port);

if (usrid == 1 && debug > 0)
{
printf("openufp started with usrname support\n");
}

if ((pid = fork()) == 0) {
struct sockaddr_in cli_addr;
socklen_t cli_size;
Expand Down Expand Up @@ -222,8 +234,16 @@ int main(int argc, char**argv) {
request = n2h2_validate(n2h2_request, msgsize);
} else {
websns_request = (struct websns_req *)msg;
websns_convert(websns_request, msg, msgsize);

//secret debug
if(debug > 3)
{
syslog(LOG_INFO, "Websense debug request output: size %d, vers_maj %d, vers_min %d, vers_pat %d, serial %d, code %d, desc %d, srcip %d, dstip %d, urlsize %d, url %s",
websns_request->size, websns_request->vers_maj, websns_request->vers_min, websns_request->vers_pat, websns_request->serial, websns_request->code, websns_request->desc, websns_request->srcip, websns_request->dstip, websns_request->urlsize, websns_request->url);
}
websns_convert(websns_request, msg, msgsize, debug);
request = websns_validate(websns_request, msgsize);

}
if (request.type == UNKNOWN) {
syslog(LOG_WARNING, "request type not known, closing connecion.");
Expand All @@ -248,8 +268,26 @@ int main(int argc, char**argv) {

// URL request
if (request.type == N2H2_REQ || request.type == WEBSNS_REQ) {
if (debug > 0)
syslog(LOG_INFO, "received url request.");
if (debug > 0) {
syslog(LOG_INFO, "received url request - Original URL: %s", request.url);
}

// Handle HTTPS for N2H2 only since IP is provided in URI:
if (strstr(https, request.url) != NULL && request.type == N2H2_REQ) {
//char substr[URL_SIZE];
//substr = strndup(request.url+8, URL_SIZE);
//isIp = isValidIpAddress(substr);

if (debug > 0) {
syslog(LOG_INFO, "received HTTPS url request");
//if (isIp) {
// syslog(LOG_INFO, "received HTTPS url request. Substring passed IP validation");
//}
}

//request.url = strndup(substr, strlen(substr));
//free(substr);
}

// check if cached
get_hash(request.url, hash);
Expand All @@ -267,20 +305,51 @@ int main(int argc, char**argv) {
denied = proxy_backend(proxy_ip, proxy_port, proxy_deny_pattern, request.url, debug);
}

// parse url to proxy
// parse url to squidguard
if (!cached && !denied && squidguard) {
denied = squidguard_backend(sg_fd, request.srcip, request.url, debug);
// check whether srcip or srcip+usrid will be used:

if (usrid == 1)
{
denied = squidguard_backend_uid(sg_fd, request.srcip, request.usr, request.url, sg_redirect, debug);
}
else
{
denied = squidguard_backend(sg_fd, request.srcip, request.url, sg_redirect, debug);
}
}

if (denied) {
if (frontend == N2H2) {
n2h2_deny(cli_fd, n2h2_request, redirect_url);
} else {
websns_deny(cli_fd, websns_request, redirect_url);
if (frontend == N2H2 && squidguard)
{
n2h2_deny(cli_fd, n2h2_request, sg_redirect);
}
else if (frontend == WEBSNS && squidguard)
{
websns_deny(cli_fd, websns_request, sg_redirect);
}
else if (frontend == N2H2)
{
n2h2_deny(cli_fd, n2h2_request, redirect_url);
}
else
{
websns_deny(cli_fd, websns_request, redirect_url);
}

if (debug > 0)
syslog(LOG_INFO, "url denied: srcip %s, dstip %s, url %s",
request.srcip, request.dstip, request.url);
{
if (usrid == 1)
{
syslog(LOG_INFO, "url denied: srcip %s, srcusr %s, dstip %s, url %s",
request.srcip, request.usr, request.dstip, request.url);
}
else
{
syslog(LOG_INFO, "url denied: srcip %s, dstip %s, url %s",
request.srcip, request.dstip, request.url);
}
}
} else {
if (frontend == N2H2) {
n2h2_accept(cli_fd, n2h2_request);
Expand Down
5 changes: 4 additions & 1 deletion openufp.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@
#include <unistd.h>
#include <syslog.h>
#include <time.h>
#include <stdbool.h>
#include <regex.h>

#define VERSION "1.07"
#define VERSION "1.08"
#define URL_SIZE 65535
#define REQ_SIZE 65535

Expand All @@ -21,6 +23,7 @@ struct uf_request {
char srcip[15];
char dstip[15];
char url[URL_SIZE];
char usr[URL_SIZE];
};

// cache
Expand Down
69 changes: 67 additions & 2 deletions squidguard.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,13 +67,19 @@ int squidguard_closefd(FILE *sg_fd[2]) {
return 0;
}

int squidguard_backend(FILE *sg_fd[2], char srcip[15], char url[URL_SIZE], int debug) {
int squidguard_backend(FILE *sg_fd[2], char srcip[15], char url[URL_SIZE], char *sg_redirect, int debug) {
char redirect_url[URL_SIZE];

if (debug > 2)
{
syslog(LOG_INFO, "squidguard: url check using IP only: %s for url %s", srcip, url);
}

if (sg_fd[1] == NULL) {
syslog(LOG_WARNING, "squidguard: could not open fd for input.");
return 0;
}

fprintf(sg_fd[1], "%s %s/ - - GET\n", url, srcip);
fflush(sg_fd[1]);

Expand All @@ -85,8 +91,61 @@ int squidguard_backend(FILE *sg_fd[2], char srcip[15], char url[URL_SIZE], int d
if (debug > 1)
syslog(LOG_INFO, "squidguard: redirect_url (%s).", redirect_url);
if (strlen(redirect_url) > 1) {
char *parse;
parse = strtok (redirect_url, " ");
strcpy(sg_redirect, parse);

if (debug > 0)
syslog(LOG_INFO, "squidguard: url blocked. parsed_red: %s -- sg_redirectURL: %s", parse, sg_redirect );

return 1;
}
if (debug > 0)
syslog(LOG_INFO, "squidguard: url accepted.");
return 0;
}
return 0;
}

int squidguard_backend_uid(FILE *sg_fd[2], char srcip[15], char srcusr[URL_SIZE], char url[URL_SIZE], char *sg_redirect, int debug) {
char redirect_url[URL_SIZE];

if (debug > 2)
{
syslog(LOG_INFO, "squidguard: url check using IP and Username : IP: %s User: %s for url %s", srcip, srcusr, url);
}

if (sg_fd[1] == NULL) {
syslog(LOG_WARNING, "squidguard: could not open fd for input.");
return 0;
}

//Check username length; if there's nothing there, use the IP only:
if (strlen(srcusr) < 1)
{
if (debug > 2)
{
syslog(LOG_INFO, "squidguard input: username missing, defaulting to IP notation");
}
srcusr[strlen(srcusr)] = '-';
}

fprintf(sg_fd[1], "%s %s/ %s - GET\n", url, srcip, srcusr);
fflush(sg_fd[1]);

if (sg_fd[0] == NULL) {
syslog(LOG_WARNING, "squidguard: could not open fd for output.");
return 0;
}
while (fgets(redirect_url, URL_SIZE, sg_fd[0]) != NULL) {
if (strlen(redirect_url) > 2) {
char *parse;
parse = strtok (redirect_url, " ");
strcpy(sg_redirect, parse);

if (debug > 0)
syslog(LOG_INFO, "squidguard: url blocked.");
syslog(LOG_INFO, "squidguard: url blocked. parsed_red: %s -- sg_redirectURL: %s", parse, sg_redirect );

return 1;
}
if (debug > 0)
Expand All @@ -96,3 +155,9 @@ int squidguard_backend(FILE *sg_fd[2], char srcip[15], char url[URL_SIZE], int d
return 0;
}

bool isValidIpAddress(char *ipAddress)
{
struct sockaddr_in sa;
int result = inet_pton(AF_INET, ipAddress, &(sa.sin_addr));
return result != 0;
}
4 changes: 2 additions & 2 deletions squidguard.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@

extern int squidguard_getfd(FILE *sg_fd[2]);
extern int squidguard_closefd(FILE *sg_fd[2]);
extern int squidguard_backend(FILE *sg_fd[2], char srcip[15], char url[URL_SIZE], int debug);

extern int squidguard_backend(FILE *sg_fd[2], char srcip[15], char url[URL_SIZE], char *sg_redirect, int debug);
extern int squidguard_backend_uid(FILE *sg_fd[2], char srcip[15], char srcusr[URL_SIZE], char url[URL_SIZE], char *sg_redirect, int debug);
25 changes: 20 additions & 5 deletions websense.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,9 @@ void websns_deny(int fd, struct websns_req *websns_request, char *redirect_url)
}

struct uf_request websns_validate(struct websns_req *websns_request, int msgsize) {
struct uf_request request = { 0, {0}, {0}, "" };
struct uf_request request = { 0, {0}, {0}, "", "" };
struct in_addr srcip, dstip;
int i;

int i, j;
request.type = UNKNOWN;

if (msgsize == WEBSNS_ALIVE_SIZE) {
Expand All @@ -89,21 +88,37 @@ struct uf_request websns_validate(struct websns_req *websns_request, int msgsize
dstip.s_addr = websns_request->dstip;
snprintf(request.srcip, sizeof(request.srcip), "%s", inet_ntoa(srcip));
snprintf(request.dstip, sizeof(request.dstip), "%s", inet_ntoa(dstip));

for(i = 0; i < ntohs(websns_request->urlsize); i++)
request.url[i] = websns_request->url[i];
{
request.url[i] = websns_request->url[i];
}
//get remaining info in payload
i = 0;
//Offset is 2+10 for the preceding TACACS:/// string
for(j = (ntohs(websns_request->urlsize)+12); j < ntohs(websns_request->size); j++)
{
request.usr[i] = websns_request->url[j];
i++;
}

return request;
}

return request;
}

void websns_convert(struct websns_req *websns_request, char msg[REQ_SIZE], int msgsize) {
void websns_convert(struct websns_req *websns_request, char msg[REQ_SIZE], int msgsize, int debug) {
char newmsg[REQ_SIZE];
int offset = 0;
int i;

// check if it's version 1
if (msgsize > WEBSNS_REQ_SIZE && ntohs(websns_request->code) == WEBSNS_REQ && ntohs(websns_request->urlsize) == 0) {
if (debug > 2)
{
syslog(LOG_INFO,"Websense v1 packet received; converting to v4");
}
// convert to version 4
for (i = 0; i < (msgsize - 2); i++) {
if (i == 24)
Expand Down
2 changes: 1 addition & 1 deletion websense.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,5 +47,5 @@ extern void websns_alive(int fd, struct websns_req *websns_request);
extern void websns_accept(int fd, struct websns_req *websns_request);
extern void websns_deny(int fd, struct websns_req *websns_request, char *redirect_url);
extern struct uf_request websns_validate(struct websns_req *websns_request, int msgsize);
extern void websns_convert(struct websns_req *websns_request, char msg[REQ_SIZE], int msgsize);
extern void websns_convert(struct websns_req *websns_request, char msg[REQ_SIZE], int msgsize, int debug);

0 comments on commit 9ecaba2

Please sign in to comment.