Penn Computing
Computing Menu Computing A-Z
Computing Home Information Systems & Computing Penn
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);
  }
}
top

Information Systems and Computing
University of Pennsylvania
Comments & Questions


University of Pennsylvania Penn Computing University of Pennsylvania Information Systems & Computing (ISC)
Information Systems and Computing, University of Pennsylvania