summaryrefslogtreecommitdiff
path: root/fp2alias.c
blob: b1f68d60ed11ab99a6253069a0e819cb62e0c6cd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
/*
  fp2alias, a basic authentication and authorization helper

  This is free and unencumbered software released into the public
  domain.
*/

#include <config.h>

#include <syslog.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>

/* This value is used in format strings as well */
#define MAX_ALIAS_LEN 32

#define DEFAULT_ALIAS_FILE "/etc/tls/aliases"

/* Get an alias from a file, or from a user */
int get_alias (const char *filename,
               const char *fingerprint,
               char *alias,
               int add_new)
{
  FILE * fd;
  char hash[65];
  char login[MAX_ALIAS_LEN + 1];
  int l;

  /* Try to find the fingerprint */
  fd = fopen(filename, "r");
  if (!fd) {
    syslog(LOG_ERR, "Can't open %s for reading: %s (errno=%d)",
           filename, strerror(errno), errno);
    return -1;
  }
  do {
    l = fscanf(fd, "%64[a-f0-9] %32[a-z0-9]\n", hash, login);
    if (! strncmp(hash, fingerprint, 64)) {
      fclose(fd);
      strncpy(alias, login, MAX_ALIAS_LEN + 1);
      return 0;
    }
  } while (l != EOF);

  /* In read-only mode, that's all */
  if (! add_new) {
    fclose(fd);
    puts("I don't recognize you.");
    return -1;
  }

  /* Ask for an alias to add */
  puts("Enter your alias, please.");
  fflush(stdout);
  l = scanf("%32[a-z0-9]", alias);
  if (l == EOF || strlen(alias) < 2) {
    fclose(fd);
    return -1;
  }

  /* Check that the alias is not taken */
  fd = freopen(filename, "a+", fd);
  if (!fd) {
    syslog(LOG_ERR, "Can't reopen %s for writing: %s (errno=%d)",
           filename, strerror(errno), errno);
    return -1;
  }
  do {
    l = fscanf(fd, "%64[a-f0-9] %32[a-z0-9]\n", hash, login);
    if (! strncmp(alias, login, MAX_ALIAS_LEN)) {
      fclose(fd);
      printf("The '%s' alias is taken already.", alias);
      return -1;
    }
  } while (l != EOF);

  /* Everything appears to be fine; add it */
  fprintf(fd, "%s %s\n", fingerprint, alias);
  fclose(fd);
  return 0;
}

void print_help (const char *name)
{
  printf("Usage: %s [option ...] [--] [<command> [argument ...]]\n", name);
  puts("Options:");
  puts(" -f <file>     a file with \"<fingerprint> <alias>\" entries");
  puts(" -a            add new aliases");
  puts(" -i <ident>    syslog ident to use");
  puts(" -e            print messages into stderr, in addition to syslog");
  puts(" -h            print this help message and exit");
}

int main (int argc,
          char **argv)
{
  int c;
  int syslog_options = 0;
  char *ident = "fp2alias";
  char *alias_file = DEFAULT_ALIAS_FILE;
  char *sha256;
  char alias[MAX_ALIAS_LEN + 1];
  int add_new = 0;

  ident = argv[0];

  while ((c = getopt (argc, argv, "f:ai:eh")) != -1)
    switch (c)
      {
      case 'f': alias_file = optarg;           break;
      case 'a': add_new = 1;                   break;
      case 'i': ident = optarg;                break;
      case 'e': syslog_options |= LOG_PERROR;  break;
      case 'h': print_help(argv[0]);           return 0;
      default:  print_help(argv[0]);           return 1;
      }

  openlog(ident, syslog_options, LOG_USER);

  sha256 = getenv("SHA256");
  if (! sha256) {
    syslog(LOG_ERR, "The SHA256 environment variable is not defined");
    closelog();
    return 1;
  }

  if (get_alias(alias_file, sha256, alias, add_new) < 0) {
    closelog();
    return 1;
  }
  syslog(LOG_INFO, "Identified %s as %s", sha256, alias);
  closelog();

  /* Run a program if one is specified */
  if (argc > optind) {
    setenv("ALIAS", alias, 1);
    return execvp(argv[optind], &argv[optind]);
  }
  return 0;
}