/* authinfo.c: * **************************************************************** * Copyright (C) 2005 Canonical Ltd * Original Authors: James Blackwell * * See the file "COPYING" for further information about * the copyright and warranty status of this work. */ #include "hackerlab/char/str.h" #include "hackerlab/machine/types.h" #include "hackerlab/fs/file-names.h" #include "hackerlab/vu/safe.h" #include "libawk/relational.h" #include "libfsutils/file-contents.h" #include "po/gettext.h" #include "libarch/authinfo.h" #include "libarch/debug.h" enum auth_fields { AUTH_MACHINE = 0, AUTH_LOGIN = 1, AUTH_PASS = 2, }; static t_uchar * arch_auth_authinfo_filename (void); static t_uchar * arch_auth_read_auth_file (void); static inline const t_uchar * find_non_whitespace (t_uchar const * const string); static inline const t_uchar * find_whitespace (t_uchar const * const string); static rel_table arch_auth_tokenize (t_uchar const * const password_list); t_uchar * arch_auth_username (t_uchar * machine) { int row; t_uchar * username = NULL; t_uchar * passwords; rel_table password_table; passwords = arch_auth_read_auth_file(); password_table = arch_auth_parse_auth_file(passwords); rel_for_each (password_table, row) { if (0 == str_cmp(machine, password_table[row][AUTH_MACHINE])) { username = str_save (0, password_table[row][AUTH_LOGIN]); break; } } rel_free_table (password_table); lim_free(0, passwords); return username; } t_uchar * arch_auth_password (t_uchar * login, t_uchar * machine) { int row; t_uchar * password = NULL; t_uchar * passwords; rel_table password_table; passwords = arch_auth_read_auth_file(); password_table = arch_auth_parse_auth_file(passwords); rel_for_each (password_table, row) { if (0 == str_cmp(machine, password_table[row][AUTH_MACHINE]) && 0 == str_cmp(login, password_table[row][AUTH_LOGIN])) { password = str_save (0, password_table[row][AUTH_PASS]); break; } } rel_free_table (password_table); lim_free(0, passwords); return password; } rel_table arch_auth_tokenize (t_uchar const * const password_list) { rel_table tokens = NULL; const t_uchar * start; const t_uchar * end; start = password_list; end = password_list + str_length(password_list); while (start < end) { t_uchar * token; const t_uchar * word_end; /* Get rid of starting whitespace. Then make sure * there is still data left */ start = find_non_whitespace (start); if (start == end) break; /* We are at the start of a token. If we have a ", that means * tokenstart is one higher, and we snarf until the ending " * Otherwise, we snarf until the next whitespace. */ if (*start == '"') { start++; word_end = str_chr_index (start, '"'); } else word_end = find_whitespace (start); /* Uh oh. We hit the end of the string before the end of the token, * so the end of the token is the end */ if (! word_end) word_end = end; /* Now we can save the token */ token = str_save_n (0, start, (word_end) - start); rel_add_records(&tokens, rel_make_record(token, 0), 0); /* One last check. If we're at the end of the string, then * adjust start thusly, so that we won't loop anymore. * If not, then move start to the next unread data and * loop back for more. */ if (word_end == end) start = end; else start = word_end + 1; lim_free(0, token); } return tokens; } rel_table arch_auth_parse_auth_file (t_uchar const * const password_list) { int rows; rel_table fields = NULL; rel_table parsed_passwords = NULL; fields = arch_auth_tokenize(password_list); rows = 0; while (rows + 3 < rel_n_records(fields)) { if ((0 != str_casecmp("machine" , fields[rows+0][0])) || (0 != str_casecmp("login" , fields[rows+2][0]))) { debug(dbg_authinfo, 6, _("Corrupt line in .authinfo\n")); /* be as fuzzy as possible in case of failure */ rows += 1; continue; } if (rows + 5 < rel_n_records(fields) && 0 == str_casecmp("password", fields[rows+4][0])) { rel_add_records(&parsed_passwords, rel_make_record(fields[rows+1][0], fields[rows+3][0], fields[rows+5][0], 0),0); rows += 6; } else { // password hasn't been provided. // machine foo.com login john rel_add_records(&parsed_passwords, rel_make_record(fields[rows+1][0], fields[rows+3][0], "", 0),0); rows += 4; } } if (rows != rel_n_records(fields)) debug(dbg_authinfo, 1, _("Garbage at end of .authinfo file\n")); rel_free_table (fields); return parsed_passwords; } t_uchar * arch_auth_read_auth_file () { t_uchar * passfile_contents = NULL; t_uchar * auth_file = arch_auth_authinfo_filename(); if (0 == safe_access (auth_file, F_OK)) passfile_contents = file_contents (auth_file); lim_free (0, auth_file); return passfile_contents; } t_uchar * arch_auth_authinfo_filename () { t_uchar *filename = NULL; t_uchar *home = NULL; home = getenv("HOME"); filename = file_name_in_vicinity(0, home, ".authinfo"); return filename; } inline const t_uchar * find_whitespace (t_uchar const * const string) { const t_uchar * tok = string; while ( *tok != 0 && ! (*tok == '\n' || *tok == '\t' || *tok == ' ')) tok++; return tok; } inline const t_uchar * find_non_whitespace (t_uchar const * const string) { const t_uchar * tok = string; while ( *tok != 0 && (*tok == '\n' || *tok == '\t' || *tok == ' ')) tok++; return tok; } /* tag: James Blackwell Sun Apr 10 23:40:34 EDT 2005 (authinfo.c) */