#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>
#include "gsscred.h"
#define MAX_ENTRY_LEN 1024
static const char credFile[] = "/etc/gss/gsscred_db";
static const char credFileTmp[] = "/etc/gss/gsscred_db.tmp";
static const int expNameTokIdLen = 2;
static const int mechOidLenLen = 2;
static const int krb5OidTagLen = 1;
static const int krb5OidLenLen = 1;
static const int nameLen = 4;
static const int krb5OidLen = 9;
#define NAME_OFFSET (expNameTokIdLen + mechOidLenLen + krb5OidTagLen + \
krb5OidLenLen + krb5OidLen + nameLen) * 2
static int matchEntry(const char *entry, const gss_buffer_t name,
const char *uid, uid_t *uidOut);
int file_addGssCredEntry(const gss_buffer_t hexName, const char *uid,
const char *comment, char **errDetails)
{
FILE *fp;
char tmpBuf[256];
if ((fp = fopen(credFile, "a")) == NULL) {
if (errDetails) {
(void) snprintf(tmpBuf, sizeof (tmpBuf),
gettext("Unable to open gsscred file [%s]"),
credFile);
*errDetails = strdup(tmpBuf);
}
return (0);
}
(void) fprintf(fp,
"%s\t%s\t%s\n", (char *)hexName->value, uid, comment);
(void) fclose(fp);
return (1);
}
int file_getGssCredEntry(const gss_buffer_t name, const char *uid,
char **errDetails)
{
FILE *fp;
char entry[MAX_ENTRY_LEN+1];
if ((fp = fopen(credFile, "r")) == NULL) {
if (errDetails) {
(void) snprintf(entry, sizeof (entry),
gettext("Unable to open gsscred file [%s]"),
credFile);
*errDetails = strdup(entry);
}
return (0);
}
while (fgets(entry, MAX_ENTRY_LEN, fp) != NULL) {
if (name == NULL && uid == NULL) {
(void) fprintf(stdout, "%s", entry);
continue;
}
if (matchEntry(entry, name, uid, NULL))
(void) fprintf(stdout, "%s", entry);
}
(void) fclose(fp);
return (1);
}
int
file_getGssCredUid(const gss_buffer_t expName, uid_t *uidOut)
{
FILE *fp;
char entry[MAX_ENTRY_LEN+1];
int retVal = 0;
if ((fp = fopen(credFile, "r")) == NULL)
return (0);
while (fgets(entry, MAX_ENTRY_LEN, fp) != NULL) {
if (matchEntry(entry, expName, NULL, uidOut)) {
retVal = 1;
}
}
(void) fclose(fp);
return (retVal);
}
int file_deleteGssCredEntry(const gss_buffer_t name, const char *uid,
char **errDetails)
{
FILE *fp, *tempFp;
char entry[MAX_ENTRY_LEN+1];
int foundOne = 0;
if (name == NULL && uid == NULL) {
if ((fp = fopen(credFile, "w")) == NULL) {
if (errDetails) {
(void) snprintf(entry, sizeof (entry),
gettext("Unable to open gsscred"
" file [%s]"),
credFile);
*errDetails = strdup(entry);
}
return (0);
}
(void) fclose(fp);
return (1);
}
if ((fp = fopen(credFile, "r")) == NULL) {
if (errDetails) {
(void) snprintf(entry, sizeof (entry),
gettext("Unable to open gsscred file [%s]"),
credFile);
*errDetails = strdup(entry);
}
return (0);
}
if ((tempFp = fopen(credFileTmp, "w")) == NULL) {
if (errDetails) {
(void) snprintf(entry, sizeof (entry),
gettext("Unable to open gsscred temporary"
" file [%s]"),
credFileTmp);
*errDetails = strdup(entry);
}
(void) fclose(fp);
return (0);
}
while (fgets(entry, MAX_ENTRY_LEN, fp) != NULL) {
if (!matchEntry(entry, name, uid, NULL))
(void) fputs(entry, tempFp);
else
foundOne = 1;
}
(void) fclose(tempFp);
(void) fclose(fp);
(void) rename(credFileTmp, credFile);
(void) unlink(credFileTmp);
if (!foundOne) {
*errDetails = strdup(gettext("No users found"));
return (0);
}
return (1);
}
static int matchEntry(const char *entry, const gss_buffer_t name,
const char *uid, uid_t *uidOut)
{
char fullEntry[MAX_ENTRY_LEN+1], *item, *item_buf, *name_buf;
char dilims[] = "\t \n";
int item_len, name_len;
char *krb5_ntok_prefix = "0401000B06092A864886F712010202";
char *gss_u_name = "2A864886F71201020101";
if (entry == NULL || isspace(*entry))
return (0);
(void) strcpy(fullEntry, entry);
if ((item = strtok(fullEntry, dilims)) == NULL)
return (0);
if (name != NULL) {
item_len = strlen(item);
name_len = name->length;
name_buf = name->value;
if (item_len < name_len)
return (0);
if (strncmp(item, name->value, name_len) != 0) {
if (strncmp(name->value, krb5_ntok_prefix,
strlen(krb5_ntok_prefix)) != 0)
return (0);
if (strncmp(item, krb5_ntok_prefix,
strlen(krb5_ntok_prefix)) != 0)
return (0);
if ((item_buf = strstr(item, gss_u_name)) == NULL)
return (0);
item_buf += strlen(gss_u_name);
name_buf += NAME_OFFSET;
if ((strlen(item_buf) != strlen(name_buf)) &&
(strncmp(item_buf + (strlen(item_buf) - 2), "00", 2)
!= 0))
return (0);
if (strncmp(item_buf, name_buf, name_len - NAME_OFFSET)
!= 0)
return (0);
} else
if (item_len != name_len)
return (0);
if (uid == NULL) {
if (uidOut) {
if ((item = strtok(NULL, dilims)) == NULL)
return (0);
*uidOut = atol(item);
}
return (1);
}
}
if (uid == NULL)
return (1);
if ((item = strtok(NULL, dilims)) == NULL)
return (0);
if (strcmp(item, uid) == 0)
return (1);
return (0);
}