From aa4bb0d95fd8f0b16b6da1f4362b392fa114e8a1 Mon Sep 17 00:00:00 2001 From: Thomas Osterried Date: Sun, 30 Oct 2005 10:54:54 +0000 Subject: - fixed bug when downloading large messages (where linux kernel returns -EAGAIN, when buffers get empty, which leaded to data loss) - fixed bug when '\r\n' was splited into two reads (trailing \r in the first read, starting \n in the second read) -> resulted in an empty line - better FD_SET(&fdread) handling - added //COMP hufman compression - could make use of the useradd(8) program for generating new accounts --- ax25/axspawn.c | 859 ++++++++++++++++++++++++++++++++++++++++++++++------ ax25/axspawn.conf | 17 +- ax25/axspawn.conf.5 | 18 +- 3 files changed, 797 insertions(+), 97 deletions(-) (limited to 'ax25') diff --git a/ax25/axspawn.c b/ax25/axspawn.c index 6c63fde..101763b 100644 --- a/ax25/axspawn.c +++ b/ax25/axspawn.c @@ -1,6 +1,6 @@ /* * - * $Id: axspawn.c,v 1.2 2002/11/03 19:51:10 mctaylor Exp $ + * $Id: axspawn.c,v 1.3 2005/10/30 10:54:54 dl9sau Exp $ * * axspawn.c - run a program from ax25d. * @@ -52,25 +52,32 @@ * # * # allow automatic creation of user accounts * create yes - * # + * + * # allow empty password field (so user may login via telnet, or pop3 their + * # mail) [default no] + * create_empty_password no + * + * # create with system utility useradd(8)? [default no] + * create_with_useradd no + * * # guest user if above is 'no' or everything else fails. Disable with "no" * guest ax25 - * # + * * # group id or name for autoaccount * group ax25 - * # + * * # first user id to use * first_uid 400 - * # + * * # maximum user id * max_uid 2000 - * # + * * # where to add the home directory for the new user - * home /home/ax25 - * # + * home /home/hams + * * # user's shell * shell /bin/bash - * # + * * # bind user id to callsign for outgoing connects. * associate yes * @@ -81,6 +88,19 @@ * "impossible" ('+') password to /etc/passwd. Login gets called with * the "-f" option, thus new users have the chance to login without * a password. (I guess this won't work with the shadow password system). + * News: there are good reasons to use empty password fields. For e.g. + * at our mailbox-system db0tud where we have no inet access, so + * every user is a ham, not a hacker. We need the empty password + * so new may use ax25 for automatical account generation, and then + * could login via telnet or poll their mail with pop3. + * But i acknowledge, that this package will mostly used by hams who + * use their computer for both, inet and ampr. So the new option + * create_empty_password is not the default, but a feature + * needed because we won't patch this code after a new release. + * the useradd method and compression implementation is the the work + * of thomas , the finetune is by me. GPL + * the compression code initialy was for tnt by dl4ybg (GPL). + * - dl9sau for db0tud team. * * The "associate" option has to be used with great care. If a user * logs on it removes any existing callsign from the translation table @@ -106,7 +126,8 @@ with new login/libc - Terry, vk2ktj. */ -#define QUEUE_DELAY 400 /* 400 msec */ +//#define QUEUE_DELAY 400 /* 400 usec */ +#define QUEUE_DELAY 100000 /* 10 msec */ #define USERPROFILE ".profile" #define PASSWDFILE "/etc/passwd" @@ -118,6 +139,7 @@ #include #include #include +#include #include #include #include @@ -125,7 +147,6 @@ #include #include #include -#include #include #include #include @@ -167,69 +188,535 @@ #define EXITDELAY 10 +struct huffencodtab { + unsigned short code; + unsigned short len; +}; + +struct huffdecodtab { + unsigned short node1; + unsigned short node2; +}; + + + +/* huffman encoding table */ +static struct huffencodtab huffencodtab[] = { +{0xab2c,15},{0xaa84,15},{0x9fc4,15},{0xab3c,15}, +{0xab1c,15},{0xaafc,15},{0xaaec,15},{0xaad4,15}, +{0xaab4,15},{0xf340,10},{0xaaa4,15},{0x7d64,15}, +{0xaadc,15},{0xf400, 7},{0xaa94,15},{0x9ff4,15}, +{0x9fd4,15},{0x7d74,15},{0xab44,15},{0xab34,15}, +{0xab24,15},{0xab14,15},{0xab04,15},{0xaaf4,15}, +{0xaae4,15},{0xab60,14},{0xab0c,15},{0xaacc,15}, +{0xaabc,15},{0xaaac,15},{0xaa9c,15},{0xaa8c,15}, +{0xc000, 3},{0x3a80, 9},{0xabc0,10},{0x0060,11}, +{0x7d40,12},{0xab5c,14},{0x0000,12},{0xab58,14}, +{0x7c00, 9},{0x3c80, 9},{0x7d00,11},{0x0010,12}, +{0x1200, 7},{0x7a00, 7},{0xb800, 6},{0x3200, 7}, +{0x2200, 7},{0xf600, 8},{0x3d00, 8},{0x9e00, 9}, +{0xbd80, 9},{0x7c80, 9},{0x0080, 9},{0xaa00, 9}, +{0xbd00, 9},{0x9f00, 9},{0x0300, 8},{0xab78,13}, +{0xab68,13},{0x3c00, 9},{0x3000, 9},{0x0020,11}, +{0x7d50,12},{0x3800, 7},{0x7800, 7},{0x9c00, 7}, +{0xfe00, 7},{0x2400, 6},{0xbc00, 8},{0x0200, 8}, +{0x0100, 8},{0xf100, 8},{0x0040,11},{0x3100, 8}, +{0xf200, 8},{0x3400, 7},{0x1c00, 7},{0x1e00, 7}, +{0xbe00, 7},{0xaba0,11},{0x3e00, 7},{0x1400, 6}, +{0x3600, 7},{0xf380, 9},{0xf080, 9},{0x2000, 8}, +{0xfc00, 8},{0x9f80,10},{0x9e80, 9},{0xab90,12}, +{0x3b80, 9},{0xab80,12},{0xab54,14},{0x3a50,13}, +{0xab50,14},{0xa000, 5},{0x1800, 6},{0x9800, 6}, +{0x7000, 5},{0x4000, 3},{0x0400, 6},{0xac00, 6}, +{0xf800, 6},{0x6000, 4},{0x3a00,10},{0xfd00, 8}, +{0x2800, 5},{0xb000, 6},{0x8000, 4},{0xb400, 6}, +{0x1000, 7},{0x7d20,12},{0xe000, 5},{0x9000, 5}, +{0xe800, 5},{0x0800, 5},{0xf700, 8},{0xa800, 7}, +{0x7d80, 9},{0xf300,10},{0x7e00, 7},{0xab48,14}, +{0x3a48,13},{0xab4c,14},{0x3a60,12},{0x9ffc,15}, +{0x9fec,15},{0x2100, 8},{0x9fdc,15},{0x9fcc,15}, +{0xf000, 9},{0x7d7c,15},{0x7d6c,15},{0x3a40,14}, +{0xab40,15},{0xab38,15},{0xab30,15},{0xab28,15}, +{0xab20,15},{0xab18,15},{0xab70,13},{0xab10,15}, +{0xab08,15},{0xab00,15},{0xaaf8,15},{0xaaf0,15}, +{0x3b00, 9},{0xaae8,15},{0xaae0,15},{0xaad8,15}, +{0xaad0,15},{0xab64,14},{0x7d30,12},{0xaac8,15}, +{0xaac0,15},{0xaab8,15},{0xaab0,15},{0xaaa8,15}, +{0xaaa0,15},{0xaa98,15},{0xaa90,15},{0xaa88,15}, +{0xaa80,15},{0x9ff8,15},{0x9ff0,15},{0x9fe8,15}, +{0x9fe0,15},{0x9fd8,15},{0x9fd0,15},{0x9fc8,15}, +{0x9fc0,15},{0x7d78,15},{0x7d70,15},{0x3a58,13}, +{0x7d68,15},{0x7d60,15},{0xab46,15},{0xab42,15}, +{0xab3e,15},{0xab3a,15},{0xab36,15},{0xab32,15}, +{0xab2e,15},{0xab2a,15},{0xab26,15},{0xab22,15}, +{0xab1e,15},{0xab1a,15},{0xab16,15},{0xab12,15}, +{0xab0e,15},{0xab0a,15},{0xab06,15},{0xab02,15}, +{0xaafe,15},{0xaafa,15},{0xaaf6,15},{0xaaf2,15}, +{0xaaee,15},{0xaaea,15},{0xaae6,15},{0xaae2,15}, +{0xaade,15},{0xaada,15},{0xaad6,15},{0xaad2,15}, +{0xaace,15},{0xaaca,15},{0xaac6,15},{0xaac2,15}, +{0xaabe,15},{0xaaba,15},{0xaab6,15},{0xaab2,15}, +{0xaaae,15},{0xaaaa,15},{0xaaa6,15},{0xaaa2,15}, +{0xaa9e,15},{0x3a70,12},{0xaa9a,15},{0xaa96,15}, +{0xaa92,15},{0x3080, 9},{0xaa8e,15},{0xaa8a,15}, +{0xaa86,15},{0xaa82,15},{0x9ffe,15},{0x9ffa,15}, +{0x9ff6,15},{0x9ff2,15},{0x9fee,15},{0x9fea,15}, +{0x9fe6,15},{0x9fe2,15},{0x9fde,15},{0x9fda,15}, +{0x9fd6,15},{0x9fd2,15},{0x9fce,15},{0x9fca,15}, +{0x9fc6,15},{0x9fc2,15},{0x7d7e,15},{0x7d7a,15}, +{0x7d76,15},{0x7d72,15},{0x7d6e,15},{0x7d6a,15}, +{0x7d66,15},{0x7d62,15},{0x3a46,15},{0x3a44,15} +}; + +/* huffman decoding table */ +static struct huffdecodtab huffdecodtab[] = { +{ 79, 1},{ 2, 66},{ 24, 3},{ 4,208}, +{292, 5},{ 6,298},{317, 7},{ 16, 8}, +{ 9,173},{ 10,116},{ 41, 11},{ 12, 37}, +{125, 13},{357, 14},{ 15,438},{ 0, 0}, +{229, 17},{ 18, 46},{ 19, 61},{ 20, 99}, +{ 21,161},{404, 22},{ 23,483},{ 1, 0}, +{306, 25},{313, 26},{294, 27},{245, 28}, +{221, 29},{231, 30},{277, 31},{ 32,103}, +{ 33,108},{ 34,339},{421, 35},{ 36,500}, +{ 2, 0},{122, 38},{353, 39},{ 40,434}, +{ 3, 0},{131, 42},{128, 43},{361, 44}, +{ 45,442},{ 4, 0},{ 56, 47},{ 52, 48}, +{135, 49},{370, 50},{ 51,450},{ 5, 0}, +{138, 53},{375, 54},{ 55,454},{ 6, 0}, +{148, 57},{ 58, 94},{381, 59},{ 60,460}, +{ 7, 0},{ 75, 62},{ 63,152},{392, 64}, +{ 65,469},{ 8, 0},{164, 67},{311, 68}, +{ 69,246},{ 70, 97},{253, 71},{257, 72}, +{ 73,270},{319, 74},{ 9, 0},{ 76,155}, +{396, 77},{ 78,473},{ 10, 0},{165, 80}, +{296, 81},{300, 82},{295, 83},{206, 84}, +{ 85,320},{193, 86},{ 87,318},{199, 88}, +{184, 89},{ 90,112},{ 91,346},{430, 92}, +{ 93,508},{ 11, 0},{379, 95},{ 96,458}, +{ 12, 0},{ 98,218},{ 13, 0},{100,158}, +{400,101},{102,478},{ 14, 0},{331,104}, +{105,328},{408,106},{107,487},{ 15, 0}, +{109,336},{417,110},{111,496},{ 16, 0}, +{113,343},{425,114},{115,504},{ 17, 0}, +{117,141},{118,186},{119,321},{351,120}, +{121,432},{ 18, 0},{355,123},{124,436}, +{ 19, 0},{359,126},{127,440},{ 20, 0}, +{364,129},{130,444},{ 21, 0},{132,145}, +{368,133},{134,448},{ 22, 0},{372,136}, +{137,452},{ 23, 0},{377,139},{140,456}, +{ 24, 0},{142,234},{143,236},{144,383}, +{ 25, 0},{366,146},{147,446},{ 26, 0}, +{387,149},{385,150},{151,462},{ 27, 0}, +{390,153},{154,467},{ 28, 0},{394,156}, +{157,471},{ 29, 0},{398,159},{160,475}, +{ 30, 0},{402,162},{163,481},{ 31, 0}, +{ 32, 0},{175,166},{214,167},{211,168}, +{169,195},{243,170},{171,281},{286,172}, +{ 33, 0},{265,174},{ 34, 0},{176,202}, +{177,315},{178,297},{179,232},{180,252}, +{181,228},{189,182},{255,183},{ 35, 0}, +{185,242},{ 36, 0},{284,187},{192,188}, +{ 37, 0},{190,241},{191,201},{ 38, 0}, +{ 39, 0},{194,227},{ 40, 0},{196,267}, +{197,220},{237,198},{ 41, 0},{200,309}, +{ 42, 0},{ 43, 0},{203,260},{204,268}, +{308,205},{ 44, 0},{244,207},{ 45, 0}, +{304,209},{210,223},{ 46, 0},{212,258}, +{238,213},{ 47, 0},{215,303},{216,249}, +{273,217},{ 48, 0},{219,316},{ 49, 0}, +{ 50, 0},{222,278},{ 51, 0},{224,264}, +{250,225},{230,226},{ 52, 0},{ 53, 0}, +{ 54, 0},{ 55, 0},{ 56, 0},{ 57, 0}, +{251,233},{ 58, 0},{363,235},{ 59, 0}, +{ 60, 0},{ 61, 0},{239,256},{240,480}, +{ 62, 0},{ 63, 0},{ 64, 0},{ 65, 0}, +{ 66, 0},{ 67, 0},{299,247},{275,248}, +{ 68, 0},{ 69, 0},{ 70, 0},{ 71, 0}, +{ 72, 0},{271,254},{ 73, 0},{ 74, 0}, +{ 75, 0},{ 76, 0},{259,269},{ 77, 0}, +{293,261},{262,263},{ 78, 0},{ 79, 0}, +{ 80, 0},{279,266},{ 81, 0},{ 82, 0}, +{ 83, 0},{ 84, 0},{ 85, 0},{342,272}, +{ 86, 0},{274,335},{ 87, 0},{276,302}, +{ 88, 0},{ 89, 0},{ 90, 0},{283,280}, +{ 91, 0},{374,282},{ 92, 0},{ 93, 0}, +{291,285},{ 94, 0},{301,287},{288,326}, +{323,289},{290,427},{ 95, 0},{ 96, 0}, +{ 97, 0},{ 98, 0},{ 99, 0},{100, 0}, +{101, 0},{102, 0},{103, 0},{104, 0}, +{105, 0},{106, 0},{107, 0},{108, 0}, +{305,307},{109, 0},{110, 0},{111, 0}, +{112, 0},{310,384},{113, 0},{312,314}, +{114, 0},{115, 0},{116, 0},{117, 0}, +{118, 0},{119, 0},{120, 0},{121, 0}, +{122, 0},{322,325},{123, 0},{349,324}, +{124, 0},{125, 0},{327,476},{126, 0}, +{406,329},{330,485},{127, 0},{412,332}, +{410,333},{334,489},{128, 0},{129, 0}, +{415,337},{338,494},{130, 0},{419,340}, +{341,498},{131, 0},{132, 0},{423,344}, +{345,502},{133, 0},{428,347},{348,506}, +{134, 0},{350,510},{135, 0},{352,433}, +{136, 0},{354,435},{137, 0},{356,437}, +{138, 0},{358,439},{139, 0},{360,441}, +{140, 0},{362,443},{141, 0},{142, 0}, +{365,445},{143, 0},{367,447},{144, 0}, +{369,449},{145, 0},{371,451},{146, 0}, +{373,453},{147, 0},{148, 0},{376,455}, +{149, 0},{378,457},{150, 0},{380,459}, +{151, 0},{382,461},{152, 0},{153, 0}, +{154, 0},{386,463},{155, 0},{388,464}, +{389,466},{156, 0},{391,468},{157, 0}, +{393,470},{158, 0},{395,472},{159, 0}, +{397,474},{160, 0},{399,477},{161, 0}, +{401,479},{162, 0},{403,482},{163, 0}, +{405,484},{164, 0},{407,486},{165, 0}, +{409,488},{166, 0},{411,490},{167, 0}, +{413,491},{414,493},{168, 0},{416,495}, +{169, 0},{418,497},{170, 0},{420,499}, +{171, 0},{422,501},{172, 0},{424,503}, +{173, 0},{426,505},{174, 0},{175, 0}, +{429,507},{176, 0},{431,509},{177, 0}, +{178, 0},{179, 0},{180, 0},{181, 0}, +{182, 0},{183, 0},{184, 0},{185, 0}, +{186, 0},{187, 0},{188, 0},{189, 0}, +{190, 0},{191, 0},{192, 0},{193, 0}, +{194, 0},{195, 0},{196, 0},{197, 0}, +{198, 0},{199, 0},{200, 0},{201, 0}, +{202, 0},{203, 0},{204, 0},{205, 0}, +{206, 0},{207, 0},{208, 0},{209, 0}, +{ 0,465},{210, 0},{211, 0},{212, 0}, +{213, 0},{214, 0},{215, 0},{216, 0}, +{217, 0},{218, 0},{219, 0},{220, 0}, +{221, 0},{222, 0},{223, 0},{224, 0}, +{225, 0},{226, 0},{227, 0},{228, 0}, +{229, 0},{230, 0},{231, 0},{232, 0}, +{233, 0},{234, 0},{235, 0},{ 0,492}, +{236, 0},{237, 0},{238, 0},{239, 0}, +{240, 0},{241, 0},{242, 0},{243, 0}, +{244, 0},{245, 0},{246, 0},{247, 0}, +{248, 0},{249, 0},{250, 0},{251, 0}, +{252, 0},{253, 0},{512,511},{254, 0}, +{255, 0} +}; + +static unsigned char mask8tab[8] = { + 0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01 +}; + +static unsigned short mask16tab[16] = { + 0x8000,0x4000,0x2000,0x1000,0x0800,0x0400,0x0200,0x0100, + 0x0080,0x0040,0x0020,0x0010,0x0008,0x0004,0x0002,0x0001 +}; + + char policy_add_user = 1; +char policy_add_empty_password = 0; +char policy_add_prog_useradd = 0; char policy_guest = 1; char policy_associate = 0; gid_t user_gid = 400; char *user_shell = "/bin/bash"; -char *start_home = "/home/funk"; +char *start_home = "/home/hams"; char *guest = "guest"; int start_uid = 400; int end_uid = 65535; int paclen = ROSE_PACLEN; /* Its the shortest ie safest */ +int huffman = 0; +int bin = 0; +int fdmaster; + struct write_queue { struct write_queue *next; char *data; - int len; + unsigned int len; }; struct write_queue *wqueue_head = NULL; struct write_queue *wqueue_tail = NULL; -long wqueue_length = 0; +long wqueue_length = 0L; + + +int encstathuf(char *src, int srclen, char *dest, int *destlen); +int decstathuf(char *src, char *dest, int srclen, int *destlen); +int write_ax25(char *s, int len, int kick); + +/*---------------------------------------------------------------------------*/ + +/* Use private function because some platforms are broken, eg 386BSD */ + +int Xtolower(int c) +{ + return (c >= 'A' && c <= 'Z') ? (c - 'A' + 'a') : c; +} + +/*---------------------------------------------------------------------------*/ + +/* Use private function because some platforms are broken, eg 386BSD */ + +int Xtoupper(int c) +{ + return (c >= 'a' && c <= 'z') ? (c - 'a' + 'A') : c; +} + +/*---------------------------------------------------------------------------*/ + +int Strcasecmp(const char *s1, const char *s2) +{ + while (Xtolower(*s1) == Xtolower(*s2)) { + if (!*s1) return 0; + s1++; + s2++; + } + return Xtolower(*s1) - Xtolower(*s2); +} + +/*---------------------------------------------------------------------------*/ + +int Strncasecmp(const char *s1, const char *s2, int n) +{ + while (--n >= 0 && Xtolower(*s1) == Xtolower(*s2)) { + if (!*s1) return 0; + s1++; + s2++; + } + return n < 0 ? 0 : Xtolower(*s1) - Xtolower(*s2); +} /* This one is in /usr/lib/libbsd.a, but not in bsd.h and fellows... weird. */ /* (found in logind.c) */ pid_t forkpty(int *, char *, void *, struct winsize *); -int _write_ax25(const char *s, int len) +/* The buffer in src (first byte length-1) is decoded into dest + (first byte length-1). If decoding is not successful, non-0 + is returned +*/ + +int encstathuf(src,srclen,dest,destlen) +char *src; +int srclen; +char *dest; +int *destlen; { - int k, m; - char *p; + char *srcptr; + char *destptr; + int wrklen; + int bit16; + int bit8; + unsigned short huffcode; + int hufflen; + + if ((src == NULL) || (dest == NULL)) { + syslog(LOG_NOTICE, "Huffman encode: src or dest NULL!"); + return(1); + } + if (srclen > 255) { + syslog(LOG_NOTICE, "Huffman encode: srclen > 255: %d", srclen); + return(1); + } + srcptr = src; + destptr = &dest[1]; + *destlen = 0; + wrklen = 0; + bit8 = 0; + *destptr = 0; + huffcode = huffencodtab[(int)*srcptr].code; + hufflen = huffencodtab[(int)*srcptr].len; + bit16 = 0; + for (;;) { + if (huffcode & mask16tab[bit16]) + *destptr |= mask8tab[bit8]; + bit8++; + if (bit8 > 7) { + destptr++; + (*destlen)++; + if ((*destlen) >= srclen) { + /* coding uneffective, use copy */ + memcpy(&dest[1],src,srclen); + dest[0] = 255; + *destlen = srclen + 1; + return(0); + } + bit8 = 0; + *destptr = 0; + } + bit16++; + if (bit16 == hufflen) { + srcptr++; + wrklen++; + if (wrklen == srclen) break; + huffcode = huffencodtab[(int)*srcptr].code; + hufflen = huffencodtab[(int)*srcptr].len; + bit16 = 0; + } + } + if (bit8 != 0) (*destlen)++; + (*destlen)++; + dest[0] = (char)(srclen-1); + return(0); +} - p = (char *) malloc(len+1); +/* The buffer in src (first byte length-1) is decoded into dest + (first byte length-1). If decoding is not successful, non-0 + is returned +*/ - if (p == NULL) - return 0; - m = 0; - for (k = 0; k < len; k++) - { - if ( (s[k] == '\r') && ((k+1) < len) && (s[k+1] == '\n') ) - continue; - else if (s[k] == '\n') - p[m++] = '\r'; - else - p[m++] = s[k]; +int decstathuf(src,dest, srclen, destlen) +char *src; +char *dest; +int srclen; +int *destlen; +{ + unsigned char *srcptr; + unsigned char *destptr; + int wrklen; + unsigned char bitmask; + unsigned short decod; + unsigned short newnode; + + if ((src == NULL) || (dest == NULL)) return(1); + + srcptr = src; + destptr = dest; + *destlen = (int)((*srcptr)+1); + srcptr++; + if (--srclen == 0) { + return(1); + } + if (*destlen == 0) { + return(1); } - - if (m) - write(1, p, m); - free(p); - return len; + if (*destlen == 256) { + /* no compression, only copy */ + memcpy(dest,src+1,srclen); + *destlen = (unsigned char)(srclen); + return(0); + } + wrklen = 0; + decod = 0; + bitmask = 0x80; + for (;;) { + while (bitmask > 0) { + if ((*srcptr) & bitmask) { + newnode = huffdecodtab[decod].node2; + if (newnode == 0) { + *destptr = (char)huffdecodtab[decod].node1; + destptr++; + wrklen++; + if (wrklen >= *destlen) break; /* decoding finished */ + decod = 0; + } + else decod = newnode; + } + else { + newnode = huffdecodtab[decod].node1; + if (huffdecodtab[decod].node2 == 0) { + *destptr = (char)huffdecodtab[decod].node1; + destptr++; + wrklen++; + if (wrklen >= *destlen) break; /* decoding finished */ + decod = 0; + } + else decod = newnode; + } + if (decod) bitmask = bitmask >> 1; + } + if (wrklen >= *destlen) break; + bitmask = 0x80; + srcptr++; + if (srclen == 0) return(1); + srclen--; + } + return(0); } -int read_ax25(char *s, int size) + +int _write_ax25(const char *s, int len) { - int len = read(0, s, size); + int i; + if (!len) + return 0; + + i = write(1, s, len); + fflush(stdout); + return (i > 0 ? i : 0); // on error, -1 is returned +} + +int read_ax25(unsigned char *s, int size) +{ + int len; int k; + char buffer[255]; + char decomp[260]; + int declen; + struct termios termios; + + if ((len = read(0, s, size)) < 0) + return len; + + if (huffman) { + if (!decstathuf(s, decomp, len, &declen)) { + *(decomp+declen) = 0; + strcpy(s, decomp); + len = declen; + } + } + if (bin) { + return(len); + } + for (k = 0; k < len; k++) if (s[k] == '\r') s[k] = '\n'; + + if (!huffman && !Strncasecmp(s, "//COMP ON\n", 10)) { + sprintf(buffer,"\r//COMP 1\r"); + write_ax25(buffer, strlen(buffer), 1); + sleep(1); + memset((char *) &termios, 0, sizeof(termios)); + termios.c_iflag = ICRNL | IXOFF | IGNBRK; + termios.c_oflag = 0; + termios.c_cflag = CS8 | CREAD | CLOCAL; + termios.c_lflag = 0; + termios.c_cc[VMIN] = 0; + termios.c_cc[VTIME] = 0; + tcsetattr(0, TCSANOW, &termios); + + huffman = 1; + strcpy(s,"\n"); + return 1; + } + + if (huffman && !Strncasecmp(s, "//COMP OFF\n", 11)) { + sprintf(buffer,"\r//COMP 0\r"); fflush(stdout); + write_ax25(buffer, strlen(buffer), 1); + sleep(1); + huffman = 0; + memset((char *) &termios, 0, sizeof(termios)); + termios.c_iflag = ICRNL | IXOFF; + termios.c_oflag = OPOST | ONLCR; + termios.c_cflag = CS8 | CREAD | CLOCAL; + termios.c_lflag = ISIG | ICANON; + termios.c_cc[VINTR] = 127; + termios.c_cc[VQUIT] = 28; + termios.c_cc[VERASE] = 8; + termios.c_cc[VKILL] = 24; + termios.c_cc[VEOF] = 4; + cfsetispeed(&termios, B19200); + cfsetospeed(&termios, B19200); + tcsetattr(0, TCSANOW, &termios); + + strcpy(s,"\n"); + return 1; + } + return len; } @@ -242,47 +729,191 @@ int read_ax25(char *s, int size) void kick_wqueue(int dummy) { char *s, *p; - struct write_queue *buf; + struct write_queue *w_buf, *new_head; + char *q, *r; + int i; + int len, curr_len; + struct itimerval itv; + int bufsize = (huffman ? 256-1 : paclen); + char decoded[260]; + int declen; - - if (wqueue_length == 0) - return; + signal(SIGALRM, SIG_IGN); + itv.it_value.tv_sec = 0; + itv.it_value.tv_usec = QUEUE_DELAY; + for (;;) { + if (wqueue_length == 0) { + return; + } - s = (char *) malloc(wqueue_length); + // recompute waitqueue + if (wqueue_head->len < bufsize && wqueue_head->next) { + int s_len; + if (!(s = malloc(bufsize))) { + break; + } + if (!(new_head = malloc(sizeof(struct write_queue)))) { + free(s); + break; + } + p = s; + s_len = 0; - p = s; + while ((w_buf = wqueue_head)) { + curr_len = (w_buf->len > bufsize-s_len ? bufsize-s_len : w_buf->len); + memcpy(p, w_buf->data, curr_len); + s_len += curr_len; + p += curr_len; + if (w_buf->len > curr_len) { + // rewrite current buffer, and break + w_buf->len -= curr_len; + for (q = w_buf->data, r = w_buf->data+curr_len, i = 0; i < w_buf->len; i++) + *q++ = *r++; + break; + } + wqueue_head = w_buf->next; + free(w_buf->data); + free(w_buf); + } + new_head->data = s; + new_head->len = s_len; + new_head->next = wqueue_head; + wqueue_head = new_head; + } + + w_buf = wqueue_head; + curr_len = w_buf->len > bufsize ? bufsize : w_buf->len; + if (huffman && !encstathuf(w_buf->data,curr_len,decoded,&declen)) { + *(decoded+declen) = 0; + s = decoded; + len = declen; + } else { + s = w_buf->data; + len = curr_len; + } + if (!_write_ax25(s, len) && errno == EAGAIN) { + // socket busy? + // don't block, user may want interrupt the jam + itv.it_value.tv_sec = 1; + break; + } + wqueue_length -= curr_len; + if (w_buf->len > curr_len) { + // there's still data to be written - copy restbuffer to left + w_buf->len -= curr_len; + for (q = w_buf->data, r = w_buf->data+curr_len, i = 0; i < w_buf->len; i++) + *q++ = *r++; + } else { + wqueue_head = w_buf->next; + free(w_buf->data); + free(w_buf); - while (wqueue_head) - { - buf = wqueue_head; - wqueue_head = buf->next; - - memcpy(p, buf->data, buf->len); - p += buf->len; - free(buf->data); - free(buf); + if (!wqueue_head) { + wqueue_tail = NULL; + return; + } + } + + // if only a few bytes are left, wait a few ms if + // new data is available in order to send "full packets" + if (wqueue_length < paclen) + break; } - _write_ax25(s, wqueue_length); - free(s); - wqueue_tail=NULL; - wqueue_length=0; + itv.it_interval.tv_sec = 0; + itv.it_interval.tv_usec = 0; + + setitimer(ITIMER_REAL, &itv, 0); + signal(SIGALRM, kick_wqueue); } -int write_ax25(const char *s, int len) +int write_ax25(char *s, int len, int kick) { struct itimerval itv, oitv; struct write_queue * buf; + struct termios termios; + static struct termios save_termios; + static struct termios save_termios_master; + static int last_ended_with_CR = 0; + + int i = 0; + int j = 0; + char *p; + if (!len) + return 0; signal(SIGALRM, SIG_IGN); + if (!bin && !strncmp(s, "//BIN ON\r", 9)) { + tcgetattr(fdmaster, &save_termios_master); + tcgetattr(0, &save_termios); + memset((char *) &termios, 0, sizeof(termios)); + termios.c_iflag = IGNBRK | IGNPAR; + termios.c_oflag = 0; + termios.c_cflag = CBAUD | CS8 | CREAD | CLOCAL; + termios.c_cflag = ~(CSTOPB|PARENB|PARODD|HUPCL); + termios.c_lflag = 0; + termios.c_cc[VMIN] = 1; + termios.c_cc[VTIME] = 0; + termios.c_cc[VSTART] = -1; + termios.c_cc[VSTOP] = -1; + tcsetattr(0, TCSANOW, &termios); + tcsetattr(fdmaster, TCSANOW, &termios); + *s= 0; len=0; + bin = 1; + kick_wqueue(0); + return 0; + } + + if (bin && !strncmp(s, "//BIN OFF\r", 10)) { + kick_wqueue(0); + bin = 0; + tcsetattr(fdmaster, TCSANOW, &save_termios_master); + tcsetattr(0, TCSANOW, &save_termios); + last_ended_with_CR = 0; + return 0; + } + + + if (!bin) { + p = s; i = 0; j = 0; + if (last_ended_with_CR) { + // \r\n was splited. wrote already \r, now ommiting \n + if (*s == '\n') { + s++, p++; + len--; + } + last_ended_with_CR = 0; + if (!len) { + if (wqueue_head) + kick_wqueue(0); + return 0; + } + } + while (j < len) { + if ((j + 1 < len) && *(p + j) == '\r' && *(p + j + 1) == '\n') { + *(p + i) = '\r'; + j++; + } + else + *(p + i) = *(p + j); + i++; j++; + } + len = i; + if (len && s[len-1] == '\r') + last_ended_with_CR = 1; + *(p+len) = 0; + } + buf = (struct write_queue *) malloc(sizeof(struct write_queue)); if (buf == NULL) return 0; buf->data = (char *) malloc(len); - if (buf->data == NULL) + if (buf->data == NULL) { + free(buf); return 0; + } memcpy(buf->data, s, len); buf->len = len; @@ -299,7 +930,7 @@ int write_ax25(const char *s, int len) wqueue_length += len; } - if (wqueue_length >= paclen) + if (wqueue_length > 7*paclen || kick || bin) { kick_wqueue(0); } else { @@ -307,7 +938,6 @@ int write_ax25(const char *s, int len) itv.it_interval.tv_usec = 0; itv.it_value.tv_sec = 0; itv.it_value.tv_usec = QUEUE_DELAY; - setitimer(ITIMER_REAL, &itv, &oitv); signal(SIGALRM, kick_wqueue); } @@ -375,6 +1005,7 @@ void new_user(char *newuser) { struct passwd pw, *pwp; uid_t uid; + char command[1024]; FILE *fp; char username[80]; char homedir[256], userdir[256]; @@ -459,30 +1090,38 @@ retry: * add the user now */ - fp = fopen(PASSWDFILE, "a+"); - if (fp == NULL) - return; + if (policy_add_prog_useradd) { + sprintf(command,"/usr/sbin/useradd -p \"%s\" -c %s -d %s -u %d -g %d -m %s", + ((policy_add_empty_password) ? "" : "+"), + username, userdir, uid, user_gid, newuser); + if (system(command) != 0) + return; + } else { + fp = fopen(PASSWDFILE, "a+"); + if (fp == NULL) + return; - pw.pw_name = newuser; - pw.pw_passwd = "+"; - pw.pw_uid = uid; - pw.pw_gid = user_gid; - pw.pw_gecos = username; - pw.pw_dir = userdir; - pw.pw_shell = user_shell; + pw.pw_name = newuser; + pw.pw_passwd = ((policy_add_empty_password) ? "" : "+"); + pw.pw_uid = uid; + pw.pw_gid = user_gid; + pw.pw_gecos = username; + pw.pw_dir = userdir; + pw.pw_shell = user_shell; - if (getpwuid(uid) != NULL) goto retry; /* oops?! */ - - if (putpwent(&pw, fp) < 0) - return; + if (getpwuid(uid) != NULL) goto retry; /* oops?! */ - flock(fd_l, LOCK_UN); - fclose(fp); + if (putpwent(&pw, fp) < 0) + return; + + flock(fd_l, LOCK_UN); + fclose(fp); + } /* * copy ax25.profile */ - + fd_a = open(CONF_AXSPAWN_PROF_FILE, O_RDONLY); if (fd_a > 0) @@ -520,10 +1159,16 @@ void read_config(void) { sscanf(buf, "%s %s", cmd, param); - if (!strncmp(cmd, "create", 5)) + if (!strncmp(cmd, "create", 6) && !cmd[6]) { policy_add_user = (param[0] == 'y'); } else + if (!strncmp(cmd, "create_empty_password", 21)) + policy_add_empty_password = (param[0] == 'y'); + else + if (!strncmp(cmd, "create_with_useradd", 19)) + policy_add_prog_useradd = (param[0] == 'y'); + else if (!strncmp(cmd, "guest", 5)) { if (!strcmp(param, "no")) @@ -601,7 +1246,6 @@ int main(int argc, char **argv) char call[20], user[20], real_user[20]; char buf[2048]; int k, cnt, digits, letters, invalid, ssid, ssidcnt, addrlen; - int fdmaster; pid_t pid = -1; char *p; fd_set fds_read, fds_err; @@ -712,7 +1356,7 @@ int main(int argc, char **argv) if ( invalid || (k < MINLEN) || (digits > 2) || (digits < 1) ) { - write_ax25(MSG_NOCALL, sizeof(MSG_NOCALL)); + write_ax25(MSG_NOCALL, sizeof(MSG_NOCALL), 1); syslog(LOG_NOTICE, "%s is not an Amateur Radio callsign\n", call); sleep(EXITDELAY); return 1; @@ -724,8 +1368,11 @@ int main(int argc, char **argv) if (p) *p = '\0'; strcpy(real_user, user); - if (wait_for_tcp) - read_ax25(buf, sizeof(buf)); /* incoming TCP/IP connection? */ + if (wait_for_tcp) { + /* incoming TCP/IP connection? */ + if (read_ax25(buf, sizeof(buf)) < 0) + exit(0); + } pw = getpwnam(user); @@ -744,7 +1391,7 @@ int main(int argc, char **argv) if (! (pw && pw->pw_uid && pw->pw_gid) ) { - write_ax25(MSG_NOTINDBF, sizeof(MSG_NOTINDBF)); + write_ax25(MSG_NOTINDBF, sizeof(MSG_NOTINDBF), 1); syslog(LOG_NOTICE, "%s (callsign: %s) not found in /etc/passwd\n", user, call); sleep(EXITDELAY); return 1; @@ -756,7 +1403,7 @@ int main(int argc, char **argv) if (pw->pw_uid == 0 || pw->pw_gid == 0) { - write_ax25(MSG_NOCALL, sizeof(MSG_NOCALL)); + write_ax25(MSG_NOCALL, sizeof(MSG_NOCALL), 1); syslog(LOG_NOTICE, "root login of %s (callsign: %s) denied\n", user, call); sleep(EXITDELAY); return 1; @@ -854,11 +1501,12 @@ int main(int argc, char **argv) while(1) { - FD_ZERO(&fds_read); - FD_ZERO(&fds_err); + FD_ZERO(&fds_read); + FD_ZERO(&fds_err); FD_SET(0, &fds_read); FD_SET(0, &fds_err); - FD_SET(fdmaster, &fds_read); + if (wqueue_length <= paclen*7) + FD_SET(fdmaster, &fds_read); FD_SET(fdmaster, &fds_err); k = select(fdmaster+1, &fds_read, NULL, &fds_err, NULL); @@ -867,13 +1515,27 @@ int main(int argc, char **argv) { if (FD_ISSET(0, &fds_err)) { + if (huffman) { + sprintf(buf,"\r//COMP 0\r"); + write_ax25(buf, strlen(buf), 1); + sleep(EXITDELAY); + } kill(pid, SIGHUP); cleanup(ptyslave+5); return 1; } if (FD_ISSET(fdmaster, &fds_err)) - { + { + /* give the last packet in the timer controlled sendqueue a chance.. */ + if (wqueue_length) { + continue; + } + if (huffman) { + sprintf(buf,"\r//COMP 0\r"); + write_ax25(buf, strlen(buf), 1); + sleep(EXITDELAY); + } cleanup(ptyslave+5); return 1; } @@ -892,17 +1554,32 @@ int main(int argc, char **argv) if (FD_ISSET(fdmaster, &fds_read)) { - cnt = read(fdmaster, buf, sizeof(buf)); - if (cnt < 0) + cnt = read(fdmaster, buf, (huffman ? 254 : sizeof(buf))); + if (cnt < 0) { + /* give the last packet in the timer controlled sendqueue a chance.. */ + if (wqueue_length) { + continue; + } + if (huffman) { + sprintf(buf,"\r//COMP 0\r"); + write_ax25(buf, strlen(buf), 1); + sleep(EXITDELAY); + } cleanup(ptyslave+5); return 1; /* Child died */ } - write_ax25(buf, cnt); + write_ax25(buf, cnt, 0); } } else if (k < 0 && errno != EINTR) { + if (huffman) { + sprintf(buf,"\r//COMP 0\r"); + write_ax25(buf, strlen(buf), 1); + sleep(EXITDELAY); + } + kill(pid, SIGHUP); /* just in case... */ cleanup(ptyslave+5); return 0; @@ -912,7 +1589,7 @@ int main(int argc, char **argv) else { syslog(LOG_ERR, "cannot fork %m, closing connection to %s\n", call); - write_ax25(MSG_CANNOTFORK, sizeof(MSG_CANNOTFORK)); + write_ax25(MSG_CANNOTFORK, sizeof(MSG_CANNOTFORK), 1); sleep(EXITDELAY); return 1; } diff --git a/ax25/axspawn.conf b/ax25/axspawn.conf index 1f0bac4..3f4db4a 100644 --- a/ax25/axspawn.conf +++ b/ax25/axspawn.conf @@ -2,12 +2,22 @@ # # allow automatic creation of user accounts create yes + +# allow empty password field (so user may login via telnet, too) [default no] +create_empty_password no +#create_empty_password yes +# create with system utility useradd(8)? [default no] +#create_with_useradd no +create_with_useradd yes + # # guest user if above is 'no' or everything else fails. Disable with "no" -guest ax25 +#guest ax25 +guest guest # # group id or name for autoaccount -group ax25 +#group ax25 +group hams # # first user id to use first_uid 400 @@ -16,7 +26,8 @@ first_uid 400 max_uid 2000 # # where to add the home directory for the new user -home /home/ax25 +#home /home/ax25 +home /home/hams # # user shell shell /bin/bash diff --git a/ax25/axspawn.conf.5 b/ax25/axspawn.conf.5 index 416ccdf..190d4c2 100644 --- a/ax25/axspawn.conf.5 +++ b/ax25/axspawn.conf.5 @@ -17,19 +17,31 @@ config file can best be seen in an example: .br create yes .br +# allow empty password field (so user may login via telnet, too) [default no] +.br +create_empty_password no +.br +#create_empty_password yes +.br +# create with system utility useradd(8)? [default no] +.br +#create_with_useradd no +.br +create_with_useradd yes +.br # .br # guest user if above is 'no' or everything else .br # fails. Disable with "no" .br -guest ax25 +guest guest .br # .br # group id or name for autoaccount .br -group ax25 +group hams .br # .br @@ -47,7 +59,7 @@ max_uid 2000 .br # where to add the home directory for the new user .br -home /home/ax25 +home /home/hams .br # .br -- cgit v1.2.3