FOR ARCHIVAL PURPOSES ONLY
The following instructions apply to using Websec
to authenticate for web applications. Websec was retired
in December 2009 and replaced
by a new authentication system, Penn Weblogin.
|
/*
* File: websec.c.
*
* Example routines to deal with querying and expiring tokens from the
* web-security module. Supporting functions are in support.c. The
* following illustrates relevant examples of returned messages. For a
* complete list of returned codes and messages, see public_messages.h.
*
* Information returned when querying a successful token:
* 203-PennNet ID ISC
* 203-9-digit PennID 123456789
* 203-Timestamp 884704647
* 203 IP Address 222.911.721.121
*
* Information returned when querying an invalid token:
* 301 Invalid token
*
* Information returned when querying a timed out token:
* 302 Token timed out
*
* Information returned when expiring a token successfully:
* 201 Success
*
* Information returned when failing to expire a token:
* 301 Invalid token
*/
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <syslog.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include "public_messages.h"
#include "support.h"
#include "websec.h"
/* Calls the web security client with the appropriate QUERY_TOKEN args */
int check_token(char *app, char *token, Token_Info **output, char **errors) {
int len;
int status;
int fail_count;
int error_count;
int outpipe[2];
pid_t pid;
char output_line[STRING_SIZE];
char *text_returned;
char *desc;
char *val;
Token_Info *p;
FILE *child_output;
if (strspn(token, VALID_CHARS) != strlen(token)) {
populate_var("invalid character received in token var", errors);
return(1);
}
if (strspn(app, VALID_CHARS) != strlen(app)) {
populate_var("invalid character received in app var", errors);
return(1);
}
p = (Token_Info *) g_alloc(sizeof(Token_Info));
p->pennnet_id = (char *) NULL;
p->PennID9 = (char *) NULL;
p->timestamp = (char *) NULL;
p->ip_address = (char *) NULL;
if (pipe(outpipe) < 0) {
syslog(LOG_ERR, "websec (fatal): failed to pipe, errno %d", errno);
return(-1);
}
if ((pid = fork()) < 0) {
syslog(LOG_ERR, "websec (fatal): failed to fork, errno %d", errno);
return(-1);
}
/* Child */
if (! pid) {
close(outpipe[0]);
if (dup2(outpipe[1], 1) < 0) {
syslog(LOG_ERR, "websec (fatal): failed to dup stdout, errno %d", errno);
exit(-1);
}
if (dup2(outpipe[1], 2) < 0) {
syslog(LOG_ERR, "websec (fatal): failed to dup stderr, errno %d", errno);
exit(-1);
}
execl(WEBSEC_EXE, WEBSEC_EXE, app, QUERY_TOKEN, token, (char *) NULL);
/* Shouldn't reach this point */
syslog(LOG_ERR, "websec (fatal): failed to execl, errno %d", errno);
exit(-1);
}
/* Parent */
close(outpipe[1]);
child_output = fdopen(outpipe[0], "r");
if (! child_output) {
syslog(LOG_ERR, "websec (fatal): failed to fdopen from pipe, errno %d",
errno);
return(-1);
}
if (waitpid(pid, &status, 0) < 0) {
syslog(LOG_ERR, "websec (fatal): could not waitpid result, errno %d",
errno);
return(-1);
}
if (status < 0) {
syslog(LOG_ERR, "websec: child process, bad exit status (%d)", status);
return(-1);
}
error_count = 0;
fail_count = 0;
while(fgets(output_line, sizeof(output_line), child_output)) {
len = strlen(output_line);
if (output_line[len-1] == '\n')
output_line[len-1] = '\0';
text_returned = strpbrk(output_line, "- ");
if (! text_returned || ! strlen(text_returned)) {
syslog(LOG_ERR, "Error breaking up return string");
error_count++;
break;
}
text_returned++;
if (output_line[0] == '2') { /* Successful return */
if (! (desc = cut(text_returned, WEBSEC_DELIMITER, 1)) ||
! (val = cut(text_returned, WEBSEC_DELIMITER, 2))) {
syslog(LOG_ERR, "Error getting returned desc and val");
error_count++;
break;
}
/* Populate necessary variables */
if (! strcmp(desc, PENNNET_ID_RESULT))
error_count = populate_var(val, &(p->pennnet_id));
else if (! strcmp(desc, PERSON_ID_RESULT))
error_count = populate_var(val, &(p->PennID9));
else if (! strcmp(desc, TIMESTAMP_RESULT))
error_count = populate_var(val, &(p->timestamp));
else if (! strcmp(desc, IP_ADDRESS_RESULT))
error_count = populate_var(val, &(p->ip_address));
free(desc);
free(val);
if (error_count) {
*errors = string_dup("An error occurred receiving response");
break;
}
}
else if (output_line[0] == '3') { /* Invalid Return */
populate_var(text_returned, errors);
fail_count++;
break;
}
else { /* Unsuccessful */
if (! (desc = cut(text_returned, WEBSEC_DELIMITER, 1))) {
populate_var("Error getting returned error description", errors);
error_count++;
break;
}
populate_var(desc, errors);
error_count++;
free(desc);
break;
}
}
if (error_count) {
*output = (Token_Info *) NULL;
return(WEBSEC_ERROR);
}
else if (fail_count) {
*output = (Token_Info *) NULL;
return(WEBSEC_FAIL);
}
else {
*output = p;
return(WEBSEC_PASS);
}
}
/* Calls the web security client with the appropriate QUERY_TOKEN args */
int expire_token(char *app, char *token, char **errors) {
int len;
int status;
int fail_count;
int error_count;
int outpipe[2];
pid_t pid;
char output_line[STRING_SIZE];
char *text_returned;
char *desc;
char *val;
FILE *child_output;
if (strspn(token, VALID_CHARS) != strlen(token)) {
populate_var("invalid character received in token var", errors);
return(1);
}
if (strspn(app, VALID_CHARS) != strlen(app)) {
populate_var("invalid character received in app var", errors);
return(1);
}
if (pipe(outpipe) < 0) {
syslog(LOG_ERR, "websec (fatal): failed to pipe, errno %d", errno);
return(-1);
}
if ((pid = fork()) < 0) {
syslog(LOG_ERR, "websec (fatal): failed to fork, errno %d", errno);
return(-1);
}
/* Child */
if (! pid) {
close(outpipe[0]);
if (dup2(outpipe[1], 1) < 0) {
syslog(LOG_ERR, "websec (fatal): failed to dup stdout, errno %d", errno);
exit(-1);
}
if (dup2(outpipe[1], 2) < 0) {
syslog(LOG_ERR, "websec (fatal): failed to dup stderr, errno %d", errno);
exit(-1);
}
execl(WEBSEC_EXE, WEBSEC_EXE, app, EXPIRE_TOKEN, token, (char *) NULL);
/* Shouldn't reach this point */
syslog(LOG_ERR, "websec (fatal): failed to execl, errno %d", errno);
exit(-1);
}
/* Parent */
close(outpipe[1]);
child_output = fdopen(outpipe[0], "r");
if (! child_output) {
syslog(LOG_ERR, "websec (fatal): failed to fdopen from pipe, errno %d",
errno);
return(-1);
}
if (waitpid(pid, &status, 0) < 0) {
syslog(LOG_ERR, "websec (fatal): could not waitpid result, errno %d",
errno);
return(-1);
}
if (status < 0) {
syslog(LOG_ERR, "websec: child process, bad exit status (%d)", status);
return(-1);
}
error_count = 0;
fail_count = 0;
fgets(output_line, sizeof(output_line), child_output);
len = strlen(output_line);
if (output_line[len-1] == '\n')
output_line[len-1] = '\0';
/* Separate the description and value from numeric return code */
text_returned = strpbrk(output_line, "- ");
if (! text_returned || ! strlen(text_returned)) {
populate_var("(client): Error breaking up return string", errors);
return(WEBSEC_ERROR);
}
text_returned++;
if (output_line[0] == '2')
return(WEBSEC_PASS);
else if (output_line[0] == '3')
return(WEBSEC_FAIL);
else {
if (! (desc = cut(text_returned, WEBSEC_DELIMITER, 1))) {
populate_var("(client): Error receiving returned description", errors);
return(WEBSEC_ERROR);
}
populate_var(desc, errors);
free(desc);
return(WEBSEC_ERROR);
}
}
|