/* 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) */
syntax highlighted by Code2HTML, v. 0.9.1