[Date Prev] [Date Index] [Date Next] [Thread Prev] [Thread Index] [Thread Next]
Anton D. Kachalov mouse@yandex-team.ru
Mon, 13 Dec 2010 19:31:16 GMT
Good day. I prepared a patch that introduces support for:1. FreeIPMI with new config keywords: "username", "password", "interface" ("lanplus" value only) and "workaround" flags ("payloadsize" flag only). Currently tested with SM X8DTU-F and Asus Z8NR-D12.
2. Multi masters. To use the same configuration file across the numbers of conservers.
3. Multi-line comments in a C-way: /* ... */4. Basic support for `clientSSLSocket' to operate over secured channel with remote console.
-- Anton D. Kachalov ITO, System Administrator
diff --git a/autologin/Makefile b/autologin/Makefile index 9827045..b4ea74a 100644 diff --git a/compat.h b/compat.h index fe49bf0..686f5e3 100644 --- a/compat.h +++ b/compat.h @@ -331,3 +331,7 @@ typedef int socklen_t; #if HAVE_DMALLOC #include <dmalloc.h> #endif + +#if HAVE_FREEIPMI +#include <ipmiconsole.h> +#endif diff --git a/config.h.in b/config.h.in index bac39de..6c99f1f 100644 --- a/config.h.in +++ b/config.h.in @@ -33,6 +33,9 @@ /* have dmalloc support */ #undef HAVE_DMALLOC +/* have freeipmi support */ +#undef HAVE_FREEIPMI + /* Define to 1 if you have the `getaudit' function. */ #undef HAVE_GETAUDIT @@ -315,6 +318,9 @@ /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME +/* Define to the home page for this package. */ +#undef PACKAGE_URL + /* Define to the version of this package. */ #undef PACKAGE_VERSION diff --git a/configure b/configure index f0a003a..6a54edb 100755 diff --git a/configure.in b/configure.in index f4e667a..181cd61 100644 --- a/configure.in +++ b/configure.in @@ -15,6 +15,7 @@ dnl AH_TEMPLATE([HAVE_POSIX_REGCOMP], [have POSIX regcomp]) AH_TEMPLATE([HAVE_PAM], [have PAM support]) AH_TEMPLATE([HAVE_OPENSSL], [have openssl support]) AH_TEMPLATE([HAVE_GSSAPI], [have gss-api support]) +AH_TEMPLATE([HAVE_FREEIPMI], [have freeipmi support]) AH_TEMPLATE([STRIP_REALM], [retry username without @REALM with gss-api authentication]) AH_TEMPLATE([HAVE_DMALLOC], [have dmalloc support]) AH_TEMPLATE([HAVE_SA_LEN],[Defined if sa_len member exists in struct sockaddr]) @@ -578,6 +579,50 @@ AC_ARG_WITH(gssapi, fi] ) +cons_with_freeipmi="NO" +AC_ARG_WITH(freeipmi, + AS_HELP_STRING([--with-freeipmi@<:@=PATH@:>@], + [Compile in FreeIPMI support]), + [if test "$withval" != "no"; then + if test "$withval" != "yes"; then + FREEIPMICPPFLAGS="-I$withval/include" + if test "$use_dash_r" != "yes"; then + FREEIPMILDFLAGS="-L$withval/lib" + else + FREEIPMIDFLAGS="-L$withval/lib -R$withval/lib" + fi + else + FREEIPMICPPFLAGS="" + FREEIPMILDFLAGS="" + fi + + oCPPFLAGS="$CPPFLAGS" + oLDFLAGS="$LDFLAGS" + oLIBS="$LIBS" + have_freeipmi=no + + CPPFLAGS="$CPPFLAGS $FREEIPMICPPFLAGS" + LDFLAGS="$LDFLAGS $FREEIPMILDFLAGS" + + AC_CHECK_HEADER([ipmiconsole.h], + [LIBS="$LIBS -lipmiconsole" + AC_MSG_CHECKING(for freeipmi libraries -lipmiconsole) + AC_TRY_LINK([#include <ipmiconsole.h> + ],[ipmiconsole_ctx_fd(0)], + [AC_MSG_RESULT(yes) + cons_with_freeipmi="YES" + AC_DEFINE(HAVE_FREEIPMI) + have_freeipmi=yes], + [AC_MSG_RESULT(no)])],) + + if test $have_freeipmi = no; then + LIBS="$oLIBS" + CPPFLAGS="$oCPPFLAGS" + LDFLAGS="$oLDFLAGS" + fi + fi] +) + cons_with_dmalloc="NO" AC_ARG_WITH(dmalloc, AS_HELP_STRING([--with-dmalloc@<:@=PATH@:>@], @@ -737,6 +782,7 @@ echo " Unix domain sockets (--with-uds) : $cons_with_uds" echo " TCP wrappers (--with-libwrap) : $cons_with_libwrap" echo " OpenSSL (--with-openssl) : $cons_with_openssl" echo " GSS-API (--with-gssapi) : $cons_with_gssapi" +echo " FreeIPMI (--with-freeipmi) : $cons_with_freeipmi" if [ $cons_with_gssapi = "YES" ]; then echo " strip @REALM (--with-striprealm): $cons_strip_realm" fi diff --git a/conserver/consent.c b/conserver/consent.c index ca3161d..65e90cf 100644 --- a/conserver/consent.c +++ b/conserver/consent.c @@ -339,6 +339,48 @@ StopInit(pCE) } } +ipmiconsole_ctx_t +#if PROTOTYPES +IpmiSOLCreate(CONSENT *pCE) +#else +IpmiSOLCreate(pCE) + CONSENT *pCE; +#endif +{ + ipmiconsole_ctx_t ctx; + struct ipmiconsole_ipmi_config ipmi; + struct ipmiconsole_protocol_config protocol; + struct ipmiconsole_engine_config engine; + + if (ipmiconsole_engine_init(1, 0) < 0) + return 0; + + ipmi.username = pCE->username; + ipmi.password = pCE->password; + ipmi.k_g = NULL; + ipmi.k_g_len = 0; + ipmi.privilege_level = -1; + ipmi.cipher_suite_id = -1; + ipmi.workaround_flags = pCE->ipmi_wrndflags; + + protocol.session_timeout_len = -1; + + protocol.retransmission_timeout_len = -1; + protocol.retransmission_backoff_count = -1; + protocol.keepalive_timeout_len = -1; + protocol.retransmission_keepalive_timeout_len = -1; + protocol.acceptable_packet_errors_count = -1; + protocol.maximum_retransmission_count = -1; + + engine.engine_flags = 0; + engine.behavior_flags = 0; + engine.debug_flags = 0; + + ctx = ipmiconsole_ctx_create(pCE->host, &ipmi, &protocol, &engine); + + return ctx; +} + /* invoke the initcmd command */ void #if PROTOTYPES @@ -1032,6 +1074,62 @@ ConsInit(pCE) TtyDev(pCE); pCE->ioState = ISNORMAL; break; + + case IPMI: + switch (pCE->intftype) { +#if HAVE_FREEIPMI + case IPMIF_LANPLUS: + if (!(pCE->ipmi_ctx = IpmiSOLCreate(pCE))) { + Error("[%s] Could not create IPMI context: forcing down", + pCE->server); + goto ipmi_sol_error; + } + + if (ipmiconsole_engine_submit_block(pCE->ipmi_ctx) < 0) { + Error("[%s] Could not connect to IPMI host `%s': forcing down", + pCE->server, pCE->host); + goto ipmi_sol_destroy; + } + + if (ipmiconsole_ctx_status(pCE->ipmi_ctx) != + IPMICONSOLE_CTX_STATUS_SOL_ESTABLISHED) { + Error("[%s] Could not establish SOL connection: forcing down", + pCE->server); + goto ipmi_sol_destroy; + } + + cofile = ipmiconsole_ctx_fd(pCE->ipmi_ctx); + if (!SetFlags(cofile, O_NONBLOCK, 0)) { + goto ipmi_sol_destroy; + } + + if ((pCE->cofile = + FileOpenFD(cofile, simpleFile)) == (CONSFILE *)0) { + Error("[%s] FileOpenFD(simpleFile) failed: forcing down", + pCE->server); + goto ipmi_sol_destroy; + } + + pCE->ioState = ISNORMAL; + pCE->stateTimer = 0; + pCE->fup = 1; + break; +ipmi_sol_destroy: + ipmiconsole_ctx_destroy(pCE->ipmi_ctx); +ipmi_sol_error: + ConsDown(pCE, FLAGTRUE, FLAGTRUE); + return; +#endif + default: + Error("[%s] unknown IPMI interface type (%d): forcing down", + pCE->server, pCE->intftype); + ConsDown(pCE, FLAGTRUE, FLAGTRUE); + return; + } + /* + ipmi_intf_session_set_sol_escape_char(pCE->intf, SOL_ESCAPE_CHARACTER_DEFAULT); + */ + break; } if (!pCE->fup) { @@ -1050,6 +1148,9 @@ ConsInit(pCE) Verbose("[%s] port %hu on %s", pCE->server, pCE->netport, pCE->host); break; + case IPMI: + Verbose("[%s] on %s", pCE->server); + break; case NOOP: Verbose("[%s] noop", pCE->server); break; diff --git a/conserver/consent.h b/conserver/consent.h index dec5f52..51e8cf6 100644 --- a/conserver/consent.h +++ b/conserver/consent.h @@ -57,9 +57,14 @@ typedef enum consType { EXEC, HOST, NOOP, - UDS + UDS, + IPMI } CONSTYPE; +typedef enum ipmiIntf { + IPMIF_LANPLUS = 0 +} IPMIF; + typedef struct names { char *name; struct names *next; @@ -92,6 +97,16 @@ typedef struct consent { /* console information */ #if defined(CRTSCTS) FLAG crtscts; /* use hardware flow control */ #endif + FLAG secured; +#if HAVE_OPENSSL + SSL_CTX *ssl_ctx; +#endif + /* type == IPMI */ + IPMIF intftype; /* IPMI interface type */ + ipmiconsole_ctx_t ipmi_ctx; /* IPMI ctx */ + int ipmi_wrndflags; /* IPMI workaround flags */ + char *username; /* Username to log as */ + char *password; /* Login Password */ /* type == HOST */ char *host; /* hostname */ unsigned short netport; /* final port | netport = portbase + */ diff --git a/conserver/cutil.c b/conserver/cutil.c index 7a51aee..676dabf 100644 --- a/conserver/cutil.c +++ b/conserver/cutil.c @@ -860,6 +860,7 @@ FileUnopen(cfp) break; #if HAVE_OPENSSL case SSLSocket: + case clientSSLSocket: retval = -1; break; #endif @@ -1000,6 +1001,7 @@ FileClose(pcfp) break; #if HAVE_OPENSSL case SSLSocket: + case clientSSLSocket: CONDDEBUG((2, "FileClose(): performing a SSL_shutdown() on fd %d", cfp->fd)); @@ -1084,6 +1086,7 @@ FileRead(cfp, buf, len) break; #if HAVE_OPENSSL case SSLSocket: + case clientSSLSocket: if (cfp->waitForWrite == FLAGTRUE) { cfp->waitForWrite = FLAGFALSE; if (cfp->wbuf->used <= 1) @@ -1283,6 +1286,7 @@ FileWrite(cfp, bufferonly, buf, len) break; #if HAVE_OPENSSL case SSLSocket: + case clientSSLSocket: if (cfp->waitForRead == FLAGTRUE) cfp->waitForRead = FLAGFALSE; while (len > 0) { @@ -1781,6 +1785,7 @@ FileStat(cfp, buf) break; #if HAVE_OPENSSL case SSLSocket: + case clientSSLSocket: retval = -1; break; #endif @@ -1823,6 +1828,7 @@ FileSeek(cfp, offset, whence) break; #if HAVE_OPENSSL case SSLSocket: + case clientSSLSocket: retval = -1; break; #endif @@ -1863,6 +1869,7 @@ FileFDNum(cfp) break; #if HAVE_OPENSSL case SSLSocket: + case clientSSLSocket: retval = cfp->fd; break; #endif @@ -1908,6 +1915,8 @@ FileGetType(cfp) #if HAVE_OPENSSL case SSLSocket: return SSLSocket; + case clientSSLSocket: + return clientSSLSocket; #endif default: return nothing; @@ -2122,6 +2131,7 @@ FileSend(cfp, msg, len, flags) break; #if HAVE_OPENSSL case SSLSocket: + case clientSSLSocket: retval = send(fdout, msg, len, flags); break; #endif @@ -2390,9 +2400,38 @@ ProbeInterfaces(bindAddr) int #if PROTOTYPES -IsMe(char *id) +IsMe(char *ids) #else -IsMe(id) +IsMe(ids) + char *ids; +#endif +{ + int rc; + char *id; + char *str; + + rc = 0; + str = strdup(ids); + for (; ; str = NULL) { + id = strtok(str, ","); + if (id == NULL) + break; + if (*id == '\0') + continue; + if (IsMeOne(id)) { + rc = 1; + break; + } + } + free(str); + return rc; +} + +int +#if PROTOTYPES +IsMeOne(char *id) +#else +IsMeOne(id) char *id; #endif { @@ -2726,7 +2765,7 @@ GetWord(fp, line, spaceok, word) if (checkInc == -2) checkInc = -1; } - if (comment) { + if (comment == 1) { if (c == '\n') comment = 0; if (checkInc >= 0) { @@ -2762,6 +2801,20 @@ GetWord(fp, line, spaceok, word) } } continue; + } else if (comment == 2) { + if (c == '*') { + comment = 3; + continue; + } + comment = 0; + BuildStringChar('/', word); + } else if (comment == 3) { + if (c == '*') + comment = 4; + continue; + } else if (comment == 4) { + comment = c == '/' ? 0 : 3; + continue; } if (backslash) { BuildStringChar(c, word); @@ -2793,6 +2846,9 @@ GetWord(fp, line, spaceok, word) comment = 1; if (checkInc == -1) checkInc = 0; + } else if (c == '/') { + comment = 2; + continue; } else if (c == '"') { quote = 1; sawQuote = 1; diff --git a/conserver/cutil.h b/conserver/cutil.h index 51a429b..8476bc9 100644 --- a/conserver/cutil.h +++ b/conserver/cutil.h @@ -37,6 +37,7 @@ enum consFileType { simplePipe, #if HAVE_OPENSSL SSLSocket, + clientSSLSocket, #endif nothing }; @@ -192,6 +193,7 @@ extern FLAG FileSawQuoteGoto PARAMS((CONSFILE *)); extern void Bye PARAMS((int)); extern void DestroyDataStructures PARAMS((void)); extern int IsMe PARAMS((char *)); +extern int IsMeOne PARAMS((char *)); extern char *PruneSpace PARAMS((char *)); extern int FileCanRead PARAMS((CONSFILE *, fd_set *, fd_set *)); extern int FileCanWrite PARAMS((CONSFILE *, fd_set *, fd_set *)); diff --git a/conserver/group.c b/conserver/group.c index e5d396f..017c78b 100644 --- a/conserver/group.c +++ b/conserver/group.c @@ -1866,6 +1866,68 @@ SendBreak(pCLServing, pCEServing, bt) #if HAVE_OPENSSL int #if PROTOTYPES +AttemptClientSSL(CONSENT *pCE) +#else +AttemptClientSSL(pCE) + CONSENT *pCE; +#endif +{ + int ret; + SSL *ssl; + + if ((ssl = FileGetSSL(pCE->cofile)) == NULL) { + pCE->ssl_ctx = SSL_CTX_new(SSLv23_client_method()); + if (pCE->ssl_ctx == (SSL_CTX *)0) { + Error + ("[%s] SSL_CTX_new() failed: forcing down", + pCE->server); + return 0; + } + SSL_CTX_set_default_verify_paths(pCE->ssl_ctx); + + /* SSL_VERIFY_NONE instructs OpenSSL not to abort SSL_connect if the + certificate is invalid. We verify the certificate separately in + ssl_check_certificate, which provides much better diagnostics + than examining the error stack after a failed SSL_connect. */ + SSL_CTX_set_verify (pCE->ssl_ctx, SSL_VERIFY_NONE, NULL); + + /* Since fd_write unconditionally assumes partial writes (and + handles them correctly), allow them in OpenSSL. */ + SSL_CTX_set_mode(pCE->ssl_ctx, SSL_MODE_ENABLE_PARTIAL_WRITE); + + /* The OpenSSL library can handle renegotiations automatically, so + tell it to do so. */ + SSL_CTX_set_mode(pCE->ssl_ctx, SSL_MODE_AUTO_RETRY); + + ssl = SSL_new(pCE->ssl_ctx); + if (ssl == (SSL *)0) { + Error + ("[%s] SSL_new() failed: forcing down", + pCE->server); + return 0; + } + + FileSetSSL(pCE->cofile, ssl); + SSL_set_fd(ssl, FileFDNum(pCE->cofile)); + SSL_set_connect_state(ssl); + } + + if ((ret = SSL_connect(ssl)) <= 0) { + ret = SSL_get_error(ssl, ret); + if (ret != SSL_ERROR_WANT_READ && ret != SSL_ERROR_WANT_READ) { + Error + ("[%s] SSL_connect(%d): %d failed: forcing down", + pCE->server, FileFDNum(pCE->cofile), ret); + return 0; + } + return -ret; + } + + return 1; +} + +int +#if PROTOTYPES AttemptSSL(CONSCLIENT *pCL) #else AttemptSSL(pCL) @@ -2167,6 +2229,11 @@ CommandExamine(pGE, pCLServing, pCEServing, tyme, args) b = pCE->baud->acrate; p = pCE->parity->key[0]; break; + case IPMI: + d = BuildTmpStringPrint("%s", pCE->host); + b = "IPMI"; + p = ' '; + break; case HOST: d = BuildTmpStringPrint("%s/%hu", pCE->host, pCE->netport); b = "Netwk"; @@ -2357,6 +2424,11 @@ CommandInfo(pGE, pCLServing, pCEServing, tyme, args) (unsigned long)pCE->ipid, pCE->execSlave, FileFDNum(pCE->cofile)); break; + case IPMI: + FilePrint(pCLServing->fd, FLAGTRUE, "!:%s,%hu", + pCE->host, + FileFDNum(pCE->cofile)); + break; case HOST: FilePrint(pCLServing->fd, FLAGTRUE, "!:%s,%hu,%s,%d:", pCE->host, pCE->netport, @@ -2613,6 +2685,7 @@ DoConsoleRead(pCEServing) FD_CLR(cofile, &winit); return; } + /* read terminal line */ if ((nr = FileRead(pCEServing->cofile, acInOrig, sizeof(acInOrig))) < 0) { @@ -4610,6 +4683,27 @@ Kiddie(pGE, sfd) int flags = 0; int cofile = FileFDNum(pCEServing->cofile); slen = sizeof(flags); + +#if HAVE_OPENSSL + if (pCEServing->secured == FLAGTRUE) { + int r; + char buf[10]; + r = AttemptClientSSL(pCEServing); + if (r == 0) { + Error + ("[%s] AttemptClientSSL(%d) failed: forcing down", + pCEServing->server, FileFDNum(pCEServing->cofile)); + /* no ConsoleError() for same reason as above */ + SendIWaitClientsMsg(pCEServing, "down]\r\n"); + ConsDown(pCEServing, FLAGTRUE, FLAGTRUE); + break; + } else if (r == -SSL_ERROR_WANT_READ || r == -SSL_ERROR_WANT_WRITE) { + /* Data not ready yet in NON_BLOCKing mode */ + continue; + } + } +#endif + /* So, getsockopt seems to return -1 if there is * something interesting in SO_ERROR under * solaris...sheesh. So, the error message has diff --git a/conserver/group.h b/conserver/group.h index 3bda519..e23d8c3 100644 --- a/conserver/group.h +++ b/conserver/group.h @@ -85,4 +85,5 @@ extern void ClientWantsWrite PARAMS((CONSCLIENT *)); extern void SendIWaitClientsMsg PARAMS((CONSENT *, char *)); #if HAVE_OPENSSL extern int AttemptSSL PARAMS((CONSCLIENT *)); +extern int AttemptClientSSL PARAMS((CONSENT *)); #endif diff --git a/conserver/main.c b/conserver/main.c index 50cdf41..58a3134 100644 --- a/conserver/main.c +++ b/conserver/main.c @@ -945,6 +945,14 @@ DumpDataStructures() pCE->execuid, pCE->execgid)); break; + case IPMI: + CONDDEBUG((1, + "DumpDataStructures(): server=%s, type=IPMI", + EMPTYSTR(pCE->server))); + CONDDEBUG((1, + "DumpDataStructures(): host=%s", + EMPTYSTR(pCE->host))); + break; case HOST: CONDDEBUG((1, "DumpDataStructures(): server=%s, type=HOST", diff --git a/conserver/master.c b/conserver/master.c index d719346..0526279 100644 --- a/conserver/master.c +++ b/conserver/master.c @@ -239,18 +239,58 @@ FindRemoteConsole(args) char *args; #endif { - REMOTE *pRC; + REMOTE *pRC; + REMOTE *pRChead; + REMOTE **ppRCcurr; + REMOTE *pRCtemp; NAMES *name; + pRCtemp = (REMOTE *)0; + pRChead = (REMOTE *)0; + ppRCcurr = &pRCtemp; for (pRC = pRCList; (REMOTE *)0 != pRC; pRC = pRC->pRCnext) { - if (strcasecmp(args, pRC->rserver) == 0) - return pRC; + if (strcasecmp(args, pRC->rserver) == 0) { + if ((pRCtemp = (REMOTE *)malloc(sizeof(REMOTE))) + == (REMOTE *)0) + OutOfMem(); + memcpy(pRCtemp, pRC, sizeof(REMOTE)); + pRCtemp->pRCnext = (REMOTE *)0; + *ppRCcurr = pRCtemp; + if (pRChead == (REMOTE *)0) + pRChead = *ppRCcurr; + ppRCcurr = &pRCtemp->pRCnext; + } for (name = pRC->aliases; name != (NAMES *)0; name = name->next) { - if (strcasecmp(args, name->name) == 0) - return pRC; + if (strcasecmp(args, name->name) == 0) { + if ((pRCtemp = (REMOTE *)malloc(sizeof(REMOTE))) + == (REMOTE *)0) + OutOfMem(); + memcpy(pRCtemp, pRC, sizeof(REMOTE)); + pRCtemp->pRCnext = (REMOTE *)0; + *ppRCcurr = pRCtemp; + if (pRChead == (REMOTE *)0) + pRChead = *ppRCcurr; + ppRCcurr = &pRCtemp->pRCnext; + } } } - return pRC; + return pRChead; +} + +void +#if PROTOTYPES +FreeRemoteConsole(REMOTE *pRChead) +#else +FindRemoteConsole(pRChead) + REMOTE *pRChead; +#endif +{ + while (pRChead != (REMOTE *)0) { + REMOTE *pRCtmp; + pRCtmp = pRChead->pRCnext; + free(pRChead); + pRChead = pRCtmp; + } } void @@ -263,6 +303,7 @@ CommandCall(pCL, args) #endif { int found; + int found_to_free = 0; REMOTE *pRC, *pRCFound; unsigned short prnum = 0; char *ambiguous = (char *)0; @@ -290,6 +331,7 @@ CommandCall(pCL, args) ambiguous = BuildTmpString(", "); ++found; pRCFound = pRC; + found_to_free = 1; } } if (found == 0 && config->autocomplete == FLAGTRUE) { @@ -363,8 +405,14 @@ CommandCall(pCL, args) "automatic redirection disabled - console on master `%s'\r\n", pRCFound->rhost); } else { - FilePrint(pCL->fd, FLAGFALSE, "@%s\r\n", - pRCFound->rhost); + REMOTE *pRCtmp = pRCFound; + while (pRCtmp != (REMOTE *)0) { + FilePrint(pCL->fd, FLAGFALSE, + ":@%s"+(pRCtmp == pRCFound ? 1 : 0), + pRCtmp->rhost); + pRCtmp = pRCtmp->pRCnext; + } + FilePrint(pCL->fd, FLAGFALSE, "\r\n"); } } else { FilePrint(pCL->fd, FLAGFALSE, "%hu\r\n", prnum); @@ -380,6 +428,8 @@ CommandCall(pCL, args) } BuildTmpString((char *)0); /* we're done - clean up */ ambiguous = (char *)0; + if (pRCFound != (REMOTE *)0 && found_to_free) + FreeRemoteConsole(pRCFound); } void diff --git a/conserver/readcfg.c b/conserver/readcfg.c index 32a76ae..3bbd863 100644 --- a/conserver/readcfg.c +++ b/conserver/readcfg.c @@ -1254,6 +1254,33 @@ DefaultItemInitrunas(id) void #if PROTOTYPES +ProcessInterface(CONSENT *c, char *id) +#else +ProcessInterface(c, id) + CONSENT *c; + char *id; +#endif +{ + if (!strcasecmp("lanplus", id)) + c->intftype = IPMIF_LANPLUS; + else + Error("invalid interface type `%s' [%s:%d]", id, file, line); +} + +void +#if PROTOTYPES +DefaultItemInterface(char *id) +#else +DefaultItemInterface(id) + char *id; +#endif +{ + CONDDEBUG((1, "DefaultItemInterface(%s) [%s:%d]", id, file, line)); + ProcessInterface(parserDefaultTemp, id); +} + +void +#if PROTOTYPES DefaultItemExecrunas(char *id) #else DefaultItemExecrunas(id) @@ -1388,6 +1415,80 @@ DefaultItemUds(id) void #if PROTOTYPES +ProcessUsername(CONSENT *c, char *id) +#else +ProcessUsername(c, id) + CONSENT *c; + char *id; +#endif +{ + if ((id == (char *)0) || (*id == '\000')) { + c->username = (char *)0; + return; + } + c->username = strdup(id); +} + +void +#if PROTOTYPES +DefaultItemUsername(char *id) +#else +DefaultItemUsername(id) + char *id; +#endif +{ + CONDDEBUG((1, "DefaultItemUsername(%s) [%s:%d]", id, file, line)); + ProcessUsername(parserDefaultTemp, id); +} + +void +#if PROTOTYPES +ProcessWorkaround(CONSENT *c, char *id) +#else +ProcessWorkaround(c, id) + CONSENT *c; + char *id; +#endif +{ + int flag; + char *token = (char *)0; + + for (token = strtok(id, ALLWORDSEP); token != (char *)0; + token = strtok(NULL, ALLWORDSEP)) { + short not; + if (token[0] == '!') { + token++; + not = 1; + } else + not = 0; + flag = 0; + if (!strcmp(token, "payloadsize")) { + flag = IPMICONSOLE_WORKAROUND_IGNORE_SOL_PAYLOAD_SIZE; + } else { + continue; + } + if (not) { + c->ipmi_wrndflags &= ~flag; + } else { + c->ipmi_wrndflags |= flag; + } + } +} + +void +#if PROTOTYPES +DefaultItemWorkaround(char *id) +#else +DefaultItemWorkaround(id) + char *id; +#endif +{ + CONDDEBUG((1, "DefaultItemWorkaround(%s) [%s:%d]", id, file, line)); + ProcessWorkaround(parserDefaultTemp, id); +} + +void +#if PROTOTYPES ProcessInclude(CONSENT *c, char *id) #else ProcessInclude(c, id) @@ -1612,22 +1713,48 @@ DefaultItemIdlestring(id) void #if PROTOTYPES -ProcessMaster(CONSENT *c, char *id) +ProcessMaster(CONSENT *c, char *ids) #else -ProcessMaster(c, id) +ProcessMaster(c, ids) CONSENT *c; - char *id; + char *ids; #endif { + char *p; + char *d; + int len; + int is_delim; + if (c->master != (char *)0) { free(c->master); c->master = (char *)0; } - if ((id == (char *)0) || (*id == '\000')) + if ((ids == (char *)0) || (*ids == '\000')) return; - if ((c->master = StrDup(id)) + if ((c->master = StrDup(ids)) == (char *)0) OutOfMem(); + /* Normalize master's hostnames */ + d = (char *)0; + p = c->master; + len = strlen(c->master); + is_delim = 0; + while (*p != '\0') { + if (*p == ':' || *p == ',' || *p == ' ') { + if (!is_delim) { + is_delim = 1; + d = p; + *p = ','; + } + } else if (is_delim) { + memmove(d+1, p, len-(p-c->master)+1); + is_delim = 0; + len -= p-d-1; + p = d; + } + p++; + } + fprintf(stderr, "Master [%s]\n", c->master); } void @@ -1757,6 +1884,34 @@ DefaultItemParity(id) void #if PROTOTYPES +ProcessPassword(CONSENT *c, char *id) +#else +ProcessPassword(c, id) + CONSENT *c; + char *id; +#endif +{ + if ((id == (char *)0) || (*id == '\000')) { + c->password = (char *)0; + return; + } + c->password = strdup(id); +} + +void +#if PROTOTYPES +DefaultItemPassword(char *id) +#else +DefaultItemPassword(id) + char *id; +#endif +{ + CONDDEBUG((1, "DefaultItemPassword(%s) [%s:%d]", id, file, line)); + ProcessPassword(parserDefaultTemp, id); +} + +void +#if PROTOTYPES ProcessPort(CONSENT *c, char *id) #else ProcessPort(c, id) @@ -2163,6 +2318,37 @@ DefaultItemRw(id) void #if PROTOTYPES +ProcessSecured(char *id, FLAG *flag) +#else +ProcessSecured(id, flag) + char *id; + FLAG *flag; +#endif +{ + if (id == (char *)0 || id[0] == '\000') + *flag = FLAGFALSE; + else if (strcasecmp("yes", id) == 0 || strcasecmp("true", id) == 0 || + strcasecmp("on", id) == 0) + *flag = FLAGTRUE; + else if (strcasecmp("no", id) == 0 || strcasecmp("false", id) == 0 || + strcasecmp("off", id) == 0) + *flag = FLAGFALSE; +} + +void +#if PROTOTYPES +DefaultItemSecured(char *id) +#else +DefaultItemSecured(id) + char *id; +#endif +{ + CONDDEBUG((1, "DefaultItemSecured(%s) [%s:%d]", id, file, line)); + ProcessSecured(id, &(parserDefaultTemp->secured)); +} + +void +#if PROTOTYPES ProcessTimestamp(CONSENT *c, char *id) #else ProcessTimestamp(c, id) @@ -2326,6 +2512,8 @@ ProcessType(c, id) } if (strcasecmp("device", id) == 0) t = DEVICE; + else if (strcasecmp("ipmi", id) == 0) + t = IPMI; else if (strcasecmp("exec", id) == 0) t = EXEC; else if (strcasecmp("host", id) == 0) @@ -2484,6 +2672,14 @@ ConsoleEnd() } } break; + case IPMI: + if (parserConsoleTemp->host == (char *)0) { + if (isMaster) + Error("[%s] console missing 'host' attribute [%s:%d]", + parserConsoleTemp->server, file, line); + invalid = 1; + } + break; case HOST: if (parserConsoleTemp->host == (char *)0) { if (isMaster) @@ -2516,8 +2712,8 @@ ConsoleEnd() break; case UNKNOWNTYPE: if (isMaster) - Error("[%s] console type unknown [%s:%d]", - parserConsoleTemp->server, file, line); + Error("[%s] console type unknown %d [%s:%d]", + parserConsoleTemp->server, parserConsoleTemp->type, file, line); invalid = 1; break; } @@ -2635,21 +2831,28 @@ ConsoleAdd(c) /* check for remote consoles */ if (!IsMe(c->master)) { if (isMaster) { - REMOTE *pRCTemp; - if ((pRCTemp = (REMOTE *)calloc(1, sizeof(REMOTE))) - == (REMOTE *)0) - OutOfMem(); - if ((pRCTemp->rhost = StrDup(c->master)) - == (char *)0) - OutOfMem(); - if ((pRCTemp->rserver = StrDup(c->server)) - == (char *)0) - OutOfMem(); - pRCTemp->aliases = c->aliases; - c->aliases = (NAMES *)0; - *ppRC = pRCTemp; - ppRC = &pRCTemp->pRCnext; - CONDDEBUG((1, "[%s] remote on %s", c->server, c->master)); + char *host; + for (host = strtok(c->master, ","); + host != (char *)0; + host = strtok(NULL, ",")) { + REMOTE *pRCTemp; + if (IsMeOne(host)) + continue; + if ((pRCTemp = (REMOTE *)calloc(1, sizeof(REMOTE))) + == (REMOTE *)0) + OutOfMem(); + if ((pRCTemp->rhost = StrDup(host)) + == (char *)0) + OutOfMem(); + if ((pRCTemp->rserver = StrDup(c->server)) + == (char *)0) + OutOfMem(); + pRCTemp->aliases = c->aliases; + c->aliases = (NAMES *)0; + *ppRC = pRCTemp; + ppRC = &pRCTemp->pRCnext; + CONDDEBUG((1, "[%s] remote on %s", c->server, pRCTemp->rhost)); + } } return; } @@ -2859,6 +3062,7 @@ ConsoleAdd(c) if (!FileBufEmpty(pCEmatch->cofile)) FD_SET(cofile, &winit); } + if (pCEmatch->initfile != (CONSFILE *)0) { int initfile = FileFDNum(pCEmatch->initfile); FD_SET(initfile, &rinit); @@ -2987,6 +3191,30 @@ ConsoleAdd(c) } #endif break; + case IPMI: + if (pCEmatch->host != (char *)0 && c->host != (char *)0) { + if (strcasecmp(pCEmatch->host, c->host) != 0) { + SwapStr(&pCEmatch->host, &c->host); + closeMatch = 0; + } + } else if (pCEmatch->host != (char *)0 || + c->host != (char *)0) { + SwapStr(&pCEmatch->host, &c->host); + closeMatch = 0; + } else if (pCEmatch->username != (char *)0 || + c->username != (char *)0) { + SwapStr(&pCEmatch->username, &c->username); + closeMatch = 0; + } else if (pCEmatch->password != (char *)0 || + c->password != (char *)0) { + SwapStr(&pCEmatch->password, &c->password); + closeMatch = 0; + } + if (pCEmatch->intftype != c->intftype) { + pCEmatch->intftype = c->intftype; + closeMatch = 0; + } + break; case HOST: if (pCEmatch->host != (char *)0 && c->host != (char *)0) { if (strcasecmp(pCEmatch->host, c->host) != 0) { @@ -3634,6 +3862,30 @@ ConsoleItemUds(id) void #if PROTOTYPES +ConsoleItemUsername(char *id) +#else +ConsoleItemUsername(id) + char *id; +#endif +{ + CONDDEBUG((1, "ConsoleItemUsername(%s) [%s:%d]", id, file, line)); + ProcessUsername(parserConsoleTemp, id); +} + +void +#if PROTOTYPES +ConsoleItemWorkaround(char *id) +#else +ConsoleItemWorkaround(id) + char *id; +#endif +{ + CONDDEBUG((1, "ConsoleItemWorkaround(%s) [%s:%d]", id, file, line)); + ProcessWorkaround(parserConsoleTemp, id); +} + +void +#if PROTOTYPES ConsoleItemInclude(char *id) #else ConsoleItemInclude(id) @@ -3742,6 +3994,18 @@ ConsoleItemParity(id) void #if PROTOTYPES +ConsoleItemPassword(char *id) +#else +ConsoleItemPassword(id) + char *id; +#endif +{ + CONDDEBUG((1, "ConsoleItemPassword(%s) [%s:%d]", id, file, line)); + ProcessPassword(parserConsoleTemp, id); +} + +void +#if PROTOTYPES ConsoleItemPort(char *id) #else ConsoleItemPort(id) @@ -4571,6 +4835,30 @@ ProcessYesNo(id, flag) void #if PROTOTYPES +ConsoleItemSecured(char *id) +#else +ConsoleItemSecured(id) + char *id; +#endif +{ + CONDDEBUG((1, "ConsoleItemSecured(%s) [%s:%d]", id, file, line)); + ProcessSecured(id, &(parserConsoleTemp->secured)); +} + +void +#if PROTOTYPES +ConsoleItemInterface(char *id) +#else +ConsoleItemInterface(id) + char *id; +#endif +{ + CONDDEBUG((1, "ConsoleItemInterface(%s) [%s:%d]", id, file, line)); + ProcessInterface(parserConsoleTemp, id); +} + +void +#if PROTOTYPES ConfigItemAutocomplete(char *id) #else ConfigItemAutocomplete(id) @@ -4874,6 +5162,7 @@ ITEM keyDefault[] = { {"idlestring", DefaultItemIdlestring}, {"idletimeout", DefaultItemIdletimeout}, {"include", DefaultItemInclude}, + {"interface", DefaultItemInterface}, {"initcmd", DefaultItemInitcmd}, {"initrunas", DefaultItemInitrunas}, {"initspinmax", DefaultItemInitspinmax}, @@ -4885,6 +5174,7 @@ ITEM keyDefault[] = { {"motd", DefaultItemMOTD}, {"options", DefaultItemOptions}, {"parity", DefaultItemParity}, + {"password", DefaultItemPassword}, {"port", DefaultItemPort}, {"portbase", DefaultItemPortbase}, {"portinc", DefaultItemPortinc}, @@ -4892,10 +5182,13 @@ ITEM keyDefault[] = { {"replstring", DefaultItemReplstring}, {"ro", DefaultItemRo}, {"rw", DefaultItemRw}, + {"secured", DefaultItemSecured}, {"timestamp", DefaultItemTimestamp}, {"type", DefaultItemType}, {"uds", DefaultItemUds}, {"udssubst", DefaultItemUdssubst}, + {"username", DefaultItemUsername}, + {"workaround", DefaultItemWorkaround}, {(char *)0, (void *)0} }; @@ -4913,17 +5206,20 @@ ITEM keyConsole[] = { {"idlestring", ConsoleItemIdlestring}, {"idletimeout", ConsoleItemIdletimeout}, {"include", ConsoleItemInclude}, + {"interface", ConsoleItemInterface}, {"initcmd", ConsoleItemInitcmd}, {"initrunas", ConsoleItemInitrunas}, {"initspinmax", ConsoleItemInitspinmax}, {"initspintimer", ConsoleItemInitspintimer}, {"initsubst", ConsoleItemInitsubst}, + {"interface", ConsoleItemInterface}, {"logfile", ConsoleItemLogfile}, {"logfilemax", ConsoleItemLogfilemax}, {"master", ConsoleItemMaster}, {"motd", ConsoleItemMOTD}, {"options", ConsoleItemOptions}, {"parity", ConsoleItemParity}, + {"password", ConsoleItemPassword}, {"port", ConsoleItemPort}, {"portbase", ConsoleItemPortbase}, {"portinc", ConsoleItemPortinc}, @@ -4931,10 +5227,13 @@ ITEM keyConsole[] = { {"replstring", ConsoleItemReplstring}, {"ro", ConsoleItemRo}, {"rw", ConsoleItemRw}, + {"secured", ConsoleItemSecured}, {"timestamp", ConsoleItemTimestamp}, {"type", ConsoleItemType}, {"uds", ConsoleItemUds}, {"udssubst", ConsoleItemUdssubst}, + {"username", ConsoleItemUsername}, + {"workaround", ConsoleItemWorkaround}, {(char *)0, (void *)0} }; diff --git a/contrib/chat/Makefile b/contrib/chat/Makefile index 8fd93b6..7485c73 100644 diff --git a/contrib/yaconserv-8.1.18-mouse-moxa-realcom-tty.patch b/contrib/yaconserv-8.1.18-mouse-moxa-realcom-tty.patch new file mode 100644 index 0000000..e46af55