diff options
-rw-r--r-- | Makefile | 16 | ||||
-rw-r--r-- | autologin.c | 154 | ||||
-rw-r--r-- | autologin.h | 43 | ||||
-rw-r--r-- | config.h | 4 | ||||
-rw-r--r-- | docs/mactelnet.1 | 6 | ||||
-rw-r--r-- | mactelnet.c | 46 |
6 files changed, 203 insertions, 66 deletions
@@ -34,7 +34,10 @@ pot: po/mactelnet.pot po/mactelnet.pot: *.c xgettext --package-name=mactelnet --msgid-bugs-address=haakon.nessjoen@gmail.com -d mactelnet -C -c_ -k_ -kgettext_noop *.c -o po/mactelnet.pot - + +autologin.o: autologin.c autologin.h + ${CC} -Wall ${CFLAGS} -c autologin.c + users.o: users.c users.h ${CC} -Wall ${CFLAGS} -DUSERSFILE='"/etc/mactelnetd.users"' -c users.c @@ -47,11 +50,14 @@ interfaces.o: interfaces.c interfaces.h md5.o: md5.c md5.h ${CC} -Wall ${CFLAGS} -c md5.c -mactelnet: config.h mactelnet.c mactelnet.h protocol.o console.c console.h interfaces.o md5.o mndp.c - ${CC} -Wall ${CFLAGS} ${LDFLAGS} -o mactelnet mactelnet.c protocol.o console.c interfaces.o md5.o -DFROM_MACTELNET mndp.c ${LIBS} +console.o: console.c + ${CC} -Wall ${CFLAGS} -c console.c + +mactelnet: config.h mactelnet.c mactelnet.h protocol.o console.o interfaces.o md5.o mndp.c autologin.o + ${CC} -Wall ${CFLAGS} ${LDFLAGS} -o mactelnet mactelnet.c protocol.o console.o interfaces.o md5.o autologin.o -DFROM_MACTELNET mndp.c ${LIBS} -mactelnetd: config.h mactelnetd.c protocol.o interfaces.o console.c console.h users.o users.h md5.o - ${CC} -Wall ${CFLAGS} ${LDFLAGS} -o mactelnetd mactelnetd.c protocol.o console.c interfaces.o users.o md5.o ${LIBS} +mactelnetd: config.h mactelnetd.c protocol.o interfaces.o console.o users.o users.h md5.o + ${CC} -Wall ${CFLAGS} ${LDFLAGS} -o mactelnetd mactelnetd.c protocol.o console.o interfaces.o users.o md5.o ${LIBS} mndp: config.h mndp.c protocol.o ${CC} -Wall ${CFLAGS} ${LDFLAGS} -o mndp mndp.c protocol.o ${LIBS} diff --git a/autologin.c b/autologin.c index 45a269a..b3d5d5e 100644 --- a/autologin.c +++ b/autologin.c @@ -1,42 +1,89 @@ +/* + Mac-Telnet - Connect to RouterOS or mactelnetd devices via MAC address + Copyright (C) 2010, Håkon Nessjøen <haakon.nessjoen@gmail.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ +#include <libintl.h> +#include <locale.h> #include <stdio.h> +#include <stdlib.h> #include <string.h> +#include <errno.h> +#include <unistd.h> +#include "autologin.h" +#include "config.h" + +#define _(String) gettext (String) + +struct autologin_profile login_profiles[AUTOLOGIN_MAXPROFILES]; + +struct autologin_profile *autologin_find_profile(char *identifier) { + int i; + struct autologin_profile *default_profile = NULL; + + if (strlen(identifier) == 0) return NULL; + + for (i = 0; i < AUTOLOGIN_MAXPROFILES; ++i) { + if (login_profiles[i].inuse && strcasecmp(identifier, login_profiles[i].identifier) == 0) { + return &login_profiles[i]; + } + if (login_profiles[i].inuse && strcasecmp("default", login_profiles[i].identifier) == 0) { + default_profile = &login_profiles[i]; + } + } + return default_profile; +} + +static char *tilde_to_path(char *path) { + char *homepath; + if (*path == '~' && (homepath = getenv("HOME"))) { + static char newpath[256]; + memset(newpath, 0, sizeof(newpath)); + strncpy(newpath, homepath, 255); + strncat(newpath, path+1, 255); + return newpath; + } + return path; +} -#define AUTOLOGIN_PATH ".mactelnet" -#define AUTOLOGIN_MAXSTR 100 -#define AUTOLOGIN_MAXPROFILES 100 - -struct autologin { - char identifier[AUTOLOGIN_MAXSTR]; - char username[AUTOLOGIN_MAXSTR]; - char password[AUTOLOGIN_MAXSTR]; - char inuse:1; - char hasUsername:1; - char hasPassword:1; -}; - -struct autologin logins[AUTOLOGIN_MAXPROFILES]; - -enum autologin_state { - ALS_NONE, - ALS_PREIDENTIFIER, - ALS_IDENTIFIER, - ALS_PREKEY, - ALS_KEY, - ALS_PREVALUE, - ALS_VALUE -}; -#define AL_NONE 0 - -int main() { +int autologin_readfile(char *configfile) { FILE *fp; char c; int i = -1; char *p; + char *file_to_read; char key[AUTOLOGIN_MAXSTR]; char value[AUTOLOGIN_MAXSTR]; int line_counter=1; enum autologin_state state = ALS_NONE; - fp = fopen(AUTOLOGIN_PATH, "r"); + + memset(login_profiles, 0, sizeof(login_profiles)); + + /* Convert ~/path to /home/username/path */ + file_to_read = tilde_to_path(configfile); + + fp = fopen(file_to_read, "r"); + if (fp <= 0) { + if (strcmp(configfile, AUTOLOGIN_PATH) == 0) { + /* Silent ignore? */ + } else { + fprintf(stderr, _("Error opening autologin file %s: %s\n"), file_to_read, strerror(errno)); + } + return 0; + } while ((c = fgetc(fp)) && !feof(fp)) { if (c == '#') { while ((c = fgetc(fp)) != '\n' && !feof(fp)); @@ -48,7 +95,7 @@ int main() { if (i == AUTOLOGIN_MAXPROFILES) { goto done; } - p = logins[i].identifier; + p = login_profiles[i].identifier; state++; break; @@ -56,7 +103,7 @@ int main() { memset(key, 0, AUTOLOGIN_MAXSTR); memset(value, 0, AUTOLOGIN_MAXSTR); p = key; - logins[i].inuse = 1; + login_profiles[i].inuse = 1; state++; break; @@ -65,6 +112,8 @@ int main() { p = value; state++; break; + default: + break; } switch (state) { @@ -76,19 +125,18 @@ int main() { case ALS_IDENTIFIER: if (c == ']') { - //fprintf(stderr, "debug: identifier %s on line %d\n", logins[i].identifier, line_counter); state = ALS_PREKEY; break; } if (c == '\n') { - fprintf(stderr, "Error on line %d in %s: New line in middle of identifier\n", line_counter, AUTOLOGIN_PATH); + fprintf(stderr, _("Error on line %d in %s: New line in middle of identifier\n"), line_counter, configfile); state = ALS_NONE; break; } *p++ = c; - if (p - logins[i].identifier == AUTOLOGIN_MAXSTR-1) { + if (p - login_profiles[i].identifier == AUTOLOGIN_MAXSTR-1) { *p = 0; - fprintf(stderr, "Error on line %d in %s: Identifier string too long.\n", line_counter, AUTOLOGIN_PATH); + fprintf(stderr, _("Error on line %d in %s: Identifier string too long.\n"), line_counter, configfile); while ((c = fgetc(fp)) != '\n' && c != ']' && !feof(fp)); state = ALS_PREKEY; break; @@ -105,18 +153,18 @@ int main() { state = ALS_PREIDENTIFIER; break; } - if (c == ' ') { // ignore whitespace + if (c == ' ') { /* ignore whitespace */ break; } if (c == '\n') { - fprintf(stderr, "Error on line %d in %s: Newline before '=' character\n", line_counter, AUTOLOGIN_PATH); + fprintf(stderr, _("Error on line %d in %s: Newline before '=' character\n"), line_counter, configfile); state = ALS_PREKEY; break; } *p++ = c; if (p - key == AUTOLOGIN_MAXSTR-1) { *p = 0; - fprintf(stderr, "Error on line %d in %s: Key string too long.\n", line_counter, AUTOLOGIN_PATH); + fprintf(stderr, _("Error on line %d in %s: Key string too long.\n"), line_counter, configfile); while ((c = fgetc(fp)) != '\n' && c != '=' && !feof(fp)); if (c == '\n') { state = ALS_PREKEY; @@ -130,30 +178,33 @@ int main() { if (p == value && c == '\n') break; if (c == '\n') { if (strncasecmp(key, "user", AUTOLOGIN_MAXSTR) == 0) { - strncpy(logins[i].username, value, AUTOLOGIN_MAXSTR); - logins[i].hasUsername = 1; + strncpy(login_profiles[i].username, value, AUTOLOGIN_MAXSTR); + login_profiles[i].hasUsername = 1; } else if (strncasecmp(key, "password", AUTOLOGIN_MAXSTR) == 0) { - strncpy(logins[i].password, value, AUTOLOGIN_MAXSTR); - logins[i].hasPassword = 1; + strncpy(login_profiles[i].password, value, AUTOLOGIN_MAXSTR); + login_profiles[i].hasPassword = 1; } else { - fprintf(stderr, "Warning on line %d of %s: Unknown parameter %s, ignoring.\n", line_counter, AUTOLOGIN_PATH, key); + fprintf(stderr, _("Warning on line %d of %s: Unknown parameter %s, ignoring.\n"), line_counter, configfile, key); } state = ALS_PREKEY; break; } - if (c == ' ') { // ignore whitespace + if (c == ' ') { /* ignore whitespace */ break; } *p++ = c; if (p - value == AUTOLOGIN_MAXSTR-1) { *p = 0; - fprintf(stderr, "Error on line %d in %s: Value string too long.\n", line_counter, AUTOLOGIN_PATH); + fprintf(stderr, _("Error on line %d in %s: Value string too long.\n"), line_counter, configfile); while ((c = fgetc(fp)) != '\n' && !feof(fp)); if (c == '\n') { state = ALS_PREKEY; } } break; + + default: + break; } if (c == '\n') { line_counter++; @@ -166,18 +217,5 @@ int main() { done: fclose(fp); - printf("\n\nConfig:\n"); - for (i = 0; i < 100; ++i) { - if (logins[i].inuse) { - printf("Profile: '%s'\n", logins[i].identifier); - if (logins[i].hasUsername) { - printf("\tUsername: '%s'\n", logins[i].username); - } - if (logins[i].hasPassword) { - printf("\tPassword: '%s'\n", logins[i].password); - } - printf("\n"); - } - } - + return 1; } diff --git a/autologin.h b/autologin.h new file mode 100644 index 0000000..2877dfe --- /dev/null +++ b/autologin.h @@ -0,0 +1,43 @@ +/* + Mac-Telnet - Connect to RouterOS or mactelnetd devices via MAC address + Copyright (C) 2010, Håkon Nessjøen <haakon.nessjoen@gmail.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ +#define AUTOLOGIN_MAXSTR 100 +#define AUTOLOGIN_MAXPROFILES 100 + +struct autologin_profile { + char identifier[AUTOLOGIN_MAXSTR]; + char username[AUTOLOGIN_MAXSTR]; + char password[AUTOLOGIN_MAXSTR]; + char inuse:1; + char hasUsername:1; + char hasPassword:1; +}; + +enum autologin_state { + ALS_NONE, + ALS_PREIDENTIFIER, + ALS_IDENTIFIER, + ALS_PREKEY, + ALS_KEY, + ALS_PREVALUE, + ALS_VALUE +}; + +extern struct autologin_profile login_profiles[AUTOLOGIN_MAXPROFILES]; +struct autologin_profile *autologin_find_profile(char *identifier); +int autologin_readfile(char *configfile); @@ -21,7 +21,9 @@ #define DEBUG 0 -#define PROGRAM_VERSION "0.4.0" +#define PROGRAM_VERSION "0.4.1" + +#define AUTOLOGIN_PATH "~/.mactelnet" #if defined(__APPLE__) && defined(__MACH__) #define PLATFORM_NAME "Mac OS X" diff --git a/docs/mactelnet.1 b/docs/mactelnet.1 index d29591d..e711f7f 100644 --- a/docs/mactelnet.1 +++ b/docs/mactelnet.1 @@ -33,6 +33,12 @@ Specify username. Without this option, you will need to enter the username in a .B \-p Specify password. Without this option, you will need to enter the password in a interactive prompt. .TP +.B \-a +Specify the path of the autologin configuration file. The default path for this file is ~/.mactelnet. The format for this file is standard INI file layout. +.TP +.B \-A +Do not use the autologin configuration file. Interactively ask for username and password. +.TP .B \-h Show summary of options. .TP diff --git a/mactelnet.c b/mactelnet.c index 7710cc1..0f86250 100644 --- a/mactelnet.c +++ b/mactelnet.c @@ -46,6 +46,7 @@ #include "config.h" #include "mactelnet.h" #include "mndp.h" +#include "autologin.h" #define PROGRAM_NAME "MAC-Telnet" @@ -76,6 +77,9 @@ static int mndp_timeout = 0; static int is_a_tty = 1; static int quiet_mode = 0; static int batch_mode = 0; +static int no_autologin = 0; + +static char autologin_path[255]; static int keepalive_counter = 0; @@ -434,18 +438,21 @@ int main (int argc, char **argv) { int result; struct mt_packet data; struct sockaddr_in si_me; + struct autologin_profile *login_profile; unsigned char buff[1500]; unsigned char print_help = 0, have_username = 0, have_password = 0; unsigned char drop_priv = 0; int c; int optval = 1; + strncpy(autologin_path, AUTOLOGIN_PATH, 254); + setlocale(LC_ALL, ""); bindtextdomain("mactelnet","/usr/share/locale"); textdomain("mactelnet"); while (1) { - c = getopt(argc, argv, "lnqt:u:p:U:vh?B"); + c = getopt(argc, argv, "lnqt:u:p:U:vh?BAa:"); if (c == -1) { break; @@ -501,6 +508,15 @@ int main (int argc, char **argv) { case 'B': batch_mode = 1; + break; + + case 'A': + no_autologin = 1; + break; + + case 'a': + strncpy(autologin_path, optarg, 254); + break; case 'h': case '?': @@ -514,7 +530,7 @@ int main (int argc, char **argv) { } if (argc - optind < 1 || print_help) { print_version(); - fprintf(stderr, _("Usage: %s <MAC|identity> [-h] [-n] [-t <timeout>] [-u <user>] [-p <password>] [-U <user>] | -l [-B] [-t <timeout>]\n"), argv[0]); + fprintf(stderr, _("Usage: %s <MAC|identity> [-h] [-n] [-a <path>] [-A] [-t <timeout>] [-u <user>] [-p <password>] [-U <user>] | -l [-B] [-t <timeout>]\n"), argv[0]); if (print_help) { fprintf(stderr, _("\nParameters:\n" @@ -526,6 +542,8 @@ int main (int argc, char **argv) { " -B Batch mode. Use computer readable output (CSV), for use with -l.\n" " -n Do not use broadcast packets. Less insecure but requires\n" " root privileges.\n" + " -a <path> Use specified path instead of the default: " AUTOLOGIN_PATH " for autologin config file.\n" + " -A Disable autologin feature.\n" " -t <timeout> Amount of seconds to wait for a response on each interface.\n" " -u <user> Specify username on command line.\n" " -p <password> Specify password on command line.\n" @@ -543,6 +561,30 @@ int main (int argc, char **argv) { quiet_mode = 1; } + if (!no_autologin) { + autologin_readfile(autologin_path); + login_profile = autologin_find_profile(argv[optind]); + + if (!quiet_mode && login_profile != NULL && (login_profile->hasUsername || login_profile->hasPassword)) { + fprintf(stderr, _("Using autologin credentials from %s\n"), autologin_path); + } + if (!have_username) { + if (login_profile != NULL && login_profile->hasUsername) { + have_username = 1; + strncpy(username, login_profile->username, sizeof(username) - 1); + username[sizeof(username) - 1] = '\0'; + } + } + + if (!have_password) { + if (login_profile != NULL && login_profile->hasPassword) { + have_password = 1; + strncpy(password, login_profile->password, sizeof(password) - 1); + password[sizeof(password) - 1] = '\0'; + } + } + } + /* Seed randomizer */ srand(time(NULL)); |