diff --git a/CHANGES b/CHANGES index 84baeef..49199bf 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,12 @@ CHANGES ======= +version 8.1.20 (Apr 4, 2014): + - IPMI serial over LAN support via FreeIPMI - based on patch by Anton + D. Kachalov + - minor cleanup of code, removal of gcc warnings and such that should + have no fuctional change + version 8.1.19 (Sep 26, 2013): - prevent select/read loop when EOF on non-pty input (console) - reported by Chris Marget @@ -932,5 +938,5 @@ before version 6.05: and enhancements of various types were applied. # -# $Id: CHANGES,v 1.238 2013/09/26 17:57:44 bryan Exp $ +# $Id: CHANGES,v 1.239 2014/04/04 16:27:38 bryan Exp $ # 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 #endif + +#if HAVE_FREEIPMI +#include +#endif diff --git a/config.h.in b/config.h.in index 05abf0e..c135e98 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 diff --git a/configure b/configure index beab856..543d495 100755 --- a/configure +++ b/configure @@ -690,6 +690,7 @@ with_openssl with_req_server_cert with_gssapi with_striprealm +with_freeipmi with_dmalloc with_pam ' @@ -1338,6 +1339,7 @@ Optional Packages: --with-gssapi[=PATH] Compile in GSS-API support --with-striprealm retry username without @REALM with gss-api authentication + --with-freeipmi[=PATH] Compile in FreeIPMI support --with-dmalloc[=PATH] Compile in dmalloc support --with-pam Enable PAM support @@ -5336,6 +5338,76 @@ fi fi +cons_with_freeipmi="NO" + +# Check whether --with-freeipmi was given. +if test "${with_freeipmi+set}" = set; then : + withval=$with_freeipmi; 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 + FREEIPMILDFLAGS="-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_fn_c_check_header_mongrel "$LINENO" "ipmiconsole.h" "ac_cv_header_ipmiconsole_h" "$ac_includes_default" +if test "x$ac_cv_header_ipmiconsole_h" = xyes; then : + LIBS="$LIBS -lipmiconsole" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for freeipmi libraries -lipmiconsole" >&5 +$as_echo_n "checking for freeipmi libraries -lipmiconsole... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +int +main () +{ +ipmiconsole_ctx_fd(0) + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + cons_with_freeipmi="YES" + $as_echo "#define HAVE_FREEIPMI 1" >>confdefs.h + + CONSLIBS="$CONSLIBS -lipmiconsole" + have_freeipmi=yes +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi + + + + LIBS="$oLIBS" + if test $have_freeipmi = no; then + CPPFLAGS="$oCPPFLAGS" + LDFLAGS="$oLDFLAGS" + fi + fi + +fi + + cons_with_dmalloc="NO" # Check whether --with-dmalloc was given. @@ -6987,6 +7059,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/configure.in b/configure.in index e0aad54..a35309a 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]) @@ -592,6 +593,51 @@ 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 + FREEIPMILDFLAGS="-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_ctx_fd(0)], + [AC_MSG_RESULT(yes) + cons_with_freeipmi="YES" + AC_DEFINE(HAVE_FREEIPMI) + CONSLIBS="$CONSLIBS -lipmiconsole" + have_freeipmi=yes], + [AC_MSG_RESULT(no)])],) + + LIBS="$oLIBS" + if test $have_freeipmi = no; then + CPPFLAGS="$oCPPFLAGS" + LDFLAGS="$oLDFLAGS" + fi + fi] +) + cons_with_dmalloc="NO" AC_ARG_WITH(dmalloc, AS_HELP_STRING([--with-dmalloc@<:@=PATH@:>@], @@ -744,6 +790,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.cf/conserver.cf.man b/conserver.cf/conserver.cf.man index a5032f3..e4c5c44 100644 --- a/conserver.cf/conserver.cf.man +++ b/conserver.cf/conserver.cf.man @@ -1,5 +1,5 @@ -.\" $Id: conserver.cf.man,v 1.84 2013/09/25 22:10:29 bryan Exp $ -.TH CONSERVER.CF 5 "2013/09/25" "conserver-8.1.19" "conserver" +.\" $Id: conserver.cf.man,v 1.85 2014/04/04 16:17:45 bryan Exp $ +.TH CONSERVER.CF 5 "2014/04/04" "conserver-8.1.20" "conserver" .SH NAME conserver.cf \- console configuration file for .BR conserver (8) @@ -616,9 +616,9 @@ Assign as the host to connect to for accessing the console. You must also set the .B port -option as well. -Normally, only consoles of type ``host'' will use this value, however -if the +option for consoles of type ``host''. +Normally, only consoles of type ``host'' and ``ipmi'' will use this value, +however if the .BR devicesubst , .BR execsubst , or @@ -652,6 +652,111 @@ If an `s', `m', or `h' is used after the specified time is interpreted as seconds, minutes, or hours. Set the timeout to zero to disable the idle timeout (the default). .TP +\f3ipmiciphersuite\fP \f2number\fP +.br +Set the IPMI cipher suite. Syntactically valid +values are -1 (the default) and greater. Check the FreeIPMI documentation +for usable values. +.TP +\f3ipmikg\fP \f2string\fP|\f3""\fP +Set the BMC authentication key K_g to +.IR string . +A K_g value is a simple character string with the exception of `\e': +.RS +.RS +.sp +.PD 0 +.TP 6 +.B \e\e +backslash +.TP +.BI \e ooo +octal representation of a character (where +.I ooo +is one to three octal digits) +.TP +.BI \e c +character +.I c +.PD +.RE +.RE +.IP +The resulting value must be no more than 20 characters. +The null string (``\f3""\fP'') is the default. +.TP +\f3impiworkaround\fP [\f3!\fP]option[\f3,\fP...]|\f3""\fP +.br +You can turn off a workaround by prefixing it with a +.RB `` ! '' +character. +So, to turn off the +.B integrity +workaround, you would use +.BR !integrity . +The following are valid +.IR option s +and their mapping to FreeIPMI settings: +.RS +.sp +.PD 0 +.TP 21 +.B activation-status +.SM SKIP_SOL_ACTIVATION_STATUS +.TP +.B auth-capabilites +.SM AUTHENTICATION_CAPABILITIES +.TP +.B channel-payload +.SM SKIP_CHANNEL_PAYLOAD_SUPPORT +.TP +.B checksum +.SM NO_CHECKSUM_CHECK +.TP +.B default +.SM DEFAULT +.TP +.B ignore-payload-size +.SM IGNORE_SOL_PAYLOAD_SIZE +.TP +.B ignore-port +.SM IGNORE_SOL_PORT +.TP +.B integrity +.SM NON_EMPTY_INTEGRITY_CHECK_VALUE +.TP +.B intel-session +.SM INTEL_2_0_SESSION +.TP +.B packet-sequence +.SM INCREMENT_SOL_PACKET_SEQUENCE +.TP +.B privilege +.SM OPEN_SESSION_PRIVILEGE +.TP +.B serial-alerts +.SM SERIAL_ALERTS_DEFERRED +.TP +.B sun-session +.SM SUN_2_0_SESSION +.TP +.B supermicro-session +.SM SUPERMICRO_2_0_SESSION +.PD +.RE +.IP +If no +.B ipmiworkaround +is specified, the ``\f3default\fP'' workaround will be used. +The null string (``\f3""\fP'') unsets all workarounds, +including ``\f3default\fP''. +See the FreeIPMI documentation for details on what workarounds affect. +.TP +\f3ipmiprivlevel\fP \f2user\fP|\f2operator\fP|\f2admin\fP +.br +Set the privilege level for the username used during IPMI authentication. +The default privilege level is ``\f2admin\fP''. +.TP \f3include\fP \f2default\fP .br The default block defined using the name @@ -932,6 +1037,13 @@ Default is Set the parity option for the console. Only consoles of type ``device'' will use this value. .TP +\f3password\fP \f2password\fP|\f3""\fP +.br +Use +.I password +during IPMI authentication. +If the null string (``\f3""\fP'') is used (the default), no password will be used. +.TP \f3port\fP \f2number\fP|\f2name\fP .br Set the port used to access the console. @@ -960,7 +1072,7 @@ terminal server by their physical numbering of or .RI 1.. n (depending on if you like zero-based or one-based numbering). -Warning: you can generate a \-1 value with this formula, +Warning: you can generate a -1 value with this formula, which will become a very high numbered positive value (since things are stored unsigned). You must also set the @@ -1101,7 +1213,7 @@ A .RB ` b ' can be specified to add logging of break sequences sent to the console. .TP -\f3type\fP \f3device\fP|\f3exec\fP|\f3host\fP|\f3noop\fP|\f3uds\fP +\f3type\fP \f3device\fP|\f3ipmi\fP|\f3exec\fP|\f3host\fP|\f3noop\fP|\f3uds\fP .br Set the type of console. A type of @@ -1110,6 +1222,16 @@ should be used for local serial ports (also set the .B device value). A type of +.RB `` ipmi '' +should be used for IPMI serial over LAN consoles (also set the +.B host +value and possibly the +.BR username , +.BR password , +and +.BR ipmi * +values). +A type of .RB `` exec '' should be used for command invocations (perhaps also set the .B exec @@ -1153,6 +1275,13 @@ See the .B devicesubst option for an explanation of the format string. If the null string (``\f3""\fP'') is used, no replacements will be done. +.TP +\f3username\fP \f2username\fP|\f3""\fP +.br +Use +.I username +during IPMI authentication. +If the null string (``\f3""\fP'') is used (the default), the ``null'' user will be used. .RE .TP \f3group\fP \f2name\fP diff --git a/conserver.cf/conserver.passwd.man b/conserver.cf/conserver.passwd.man index 76b9ca8..03d408d 100644 --- a/conserver.cf/conserver.passwd.man +++ b/conserver.cf/conserver.passwd.man @@ -1,5 +1,5 @@ .\" $Id: conserver.passwd.man,v 1.10 2004/01/08 16:12:33 bryan Exp $ -.TH CONSERVER.PASSWD 5 "2004/01/08" "conserver-8.1.19" "conserver" +.TH CONSERVER.PASSWD 5 "2004/01/08" "conserver-8.1.20" "conserver" .SH NAME conserver.passwd \- user access information for .BR conserver (8) diff --git a/conserver.html b/conserver.html index 89a6192..4c62e91 100644 --- a/conserver.html +++ b/conserver.html @@ -177,8 +177,8 @@ body {

Downloading

-

The current version, released on Sep 26, 2013, is - 8.1.19.tar.gz. See the The current version, released on Apr 4, 2014, is + 8.1.20.tar.gz. See the CHANGES file for information on the latest updates.

diff --git a/conserver/client.c b/conserver/client.c index 07d9fbc..214b81c 100644 --- a/conserver/client.c +++ b/conserver/client.c @@ -1,5 +1,5 @@ /* - * $Id: client.c,v 5.95 2013/09/25 22:10:29 bryan Exp $ + * $Id: client.c,v 5.96 2014/04/02 04:45:31 bryan Exp $ * * Copyright conserver.com, 2000 * @@ -131,7 +131,7 @@ Replay(pCE, fdOut, back) STRING *line = (STRING *)0; off_t file_pos; off_t buf_pos; - char *buf; + char *buf = (char *)0; char *bp = (char *)0; int ch; struct stat stLog; diff --git a/conserver/consent.c b/conserver/consent.c index 4317b6e..ed5f8f2 100644 --- a/conserver/consent.c +++ b/conserver/consent.c @@ -1,5 +1,5 @@ /* - * $Id: consent.c,v 5.153 2013/09/26 17:32:54 bryan Exp $ + * $Id: consent.c,v 5.154 2014/04/02 04:45:31 bryan Exp $ * * Copyright conserver.com, 2000 * @@ -339,6 +339,54 @@ StopInit(pCE) } } +#if HAVE_FREEIPMI +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; + if (pCE->ipmikg->used <= 1) { /* 1 == NULL only */ + ipmi.k_g = NULL; + ipmi.k_g_len = 0; + } else { + ipmi.k_g = (unsigned char *)pCE->ipmikg->string; + ipmi.k_g_len = pCE->ipmikg->used - 1; + } + ipmi.privilege_level = pCE->ipmiprivlevel; + ipmi.cipher_suite_id = pCE->ipmiciphersuite; + ipmi.workaround_flags = pCE->ipmiworkaround; + + 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 = IPMICONSOLE_ENGINE_OUTPUT_ON_SOL_ESTABLISHED; + engine.behavior_flags = 0; + engine.debug_flags = 0; + + ctx = ipmiconsole_ctx_create(pCE->host, &ipmi, &protocol, &engine); + + return ctx; +} +#endif + /* invoke the initcmd command */ void #if PROTOTYPES @@ -728,6 +776,14 @@ ConsDown(pCE, downHard, force) FD_CLR(cofile, &winit); FileClose(&pCE->cofile); } +#if HAVE_FREEIPMI + /* need to do this after cofile close above as + * ipmiconsole_ctx_destroy will close the fd */ + if (pCE->ipmictx != (ipmiconsole_ctx_t) 0) { + ipmiconsole_ctx_destroy(pCE->ipmictx); + pCE->ipmictx = (ipmiconsole_ctx_t) 0; + } +#endif if (pCE->fdlog != (CONSFILE *)0) { if (pCE->nolog) { TagLogfile(pCE, "Console logging restored"); @@ -1039,6 +1095,56 @@ ConsInit(pCE) TtyDev(pCE); pCE->ioState = ISNORMAL; break; + +#if HAVE_FREEIPMI + case IPMI: + if (!(pCE->ipmictx = IpmiSOLCreate(pCE))) { + Error("[%s] Could not create IPMI context: forcing down", + pCE->server); + ConsDown(pCE, FLAGTRUE, FLAGTRUE); + return; + } + + if (ipmiconsole_engine_submit(pCE->ipmictx, NULL, NULL) < 0) { + Error + ("[%s] Could not connect to IPMI host `%s': forcing down", + pCE->server, pCE->host); + ConsDown(pCE, FLAGTRUE, FLAGTRUE); + return; + } + + cofile = ipmiconsole_ctx_fd(pCE->ipmictx); + if (!SetFlags(cofile, O_NONBLOCK, 0)) { + ConsDown(pCE, FLAGTRUE, FLAGTRUE); + return; + } + + if ((pCE->cofile = + FileOpenFD(cofile, simpleFile)) == (CONSFILE *)0) { + Error("[%s] FileOpenFD(simpleFile) failed: forcing down", + pCE->server); + ConsDown(pCE, FLAGTRUE, FLAGTRUE); + return; + } + + if (ipmiconsole_ctx_status(pCE->ipmictx) == + IPMICONSOLE_CTX_STATUS_SOL_ESTABLISHED) { + /* Read in the NULL from OUTPUT_ON_SOL_ESTABLISHED flag */ + char b[1]; + FileRead(pCE->cofile, b, 1); /* trust it's NULL */ + pCE->ioState = ISNORMAL; + pCE->stateTimer = 0; + } else { + /* Error status cases will be handled in Kiddie() */ + pCE->ioState = INCONNECT; + pCE->stateTimer = time((time_t *)0) + CONNECTTIMEOUT; + if (timers[T_STATE] == (time_t)0 || + timers[T_STATE] > pCE->stateTimer) + timers[T_STATE] = pCE->stateTimer; + } + pCE->fup = 1; + break; +#endif } if (!pCE->fup) { @@ -1057,6 +1163,11 @@ ConsInit(pCE) Verbose("[%s] port %hu on %s", pCE->server, pCE->netport, pCE->host); break; +#if HAVE_FREEIPMI + case IPMI: + Verbose("[%s] on %s", pCE->server); + break; +#endif case NOOP: Verbose("[%s] noop", pCE->server); break; @@ -1073,7 +1184,12 @@ ConsInit(pCE) /* if we're waiting for connect() to finish, watch the * write bit, otherwise watch for the read bit */ - if (pCE->ioState == INCONNECT) + if (pCE->ioState == INCONNECT +#if HAVE_FREEIPMI + /* We wait for read() with the libipmiconsole */ + && pCE->type != IPMI +#endif + ) FD_SET(cofile, &winit); else FD_SET(cofile, &rinit); diff --git a/conserver/consent.h b/conserver/consent.h index 3f13e2c..1600e03 100644 --- a/conserver/consent.h +++ b/conserver/consent.h @@ -1,5 +1,5 @@ /* - * $Id: consent.h,v 5.72 2013/09/26 17:32:55 bryan Exp $ + * $Id: consent.h,v 5.74 2014/04/04 16:17:10 bryan Exp $ * * Copyright conserver.com, 2000 * @@ -57,9 +57,19 @@ typedef enum consType { EXEC, HOST, NOOP, - UDS + UDS, +#if HAVE_FREEIPMI + IPMI, +#endif } CONSTYPE; +#if HAVE_FREEIPMI +#define IPMIL_UNKNOWN (0) +#define IPMIL_USER (IPMICONSOLE_PRIVILEGE_USER+1) +#define IPMIL_OPERATOR (IPMICONSOLE_PRIVILEGE_OPERATOR+1) +#define IPMIL_ADMIN (IPMICONSOLE_PRIVILEGE_ADMIN+1) +#endif + typedef struct names { char *name; struct names *next; @@ -91,6 +101,17 @@ typedef struct consent { /* console information */ FLAG ixoff; /* XON/XOFF flow control on input */ #if defined(CRTSCTS) FLAG crtscts; /* use hardware flow control */ +#endif +#if HAVE_FREEIPMI + /* type == IPMI */ + int ipmiprivlevel; /* IPMI authentication level */ + ipmiconsole_ctx_t ipmictx; /* IPMI ctx */ + unsigned int ipmiworkaround; /* IPMI workaround flags */ + short ipmiwrkset; /* workaround flags set in config */ + int ipmiciphersuite; /* IPMI cipher suite */ + char *username; /* Username to log as */ + char *password; /* Login Password */ + STRING *ipmikg; /* IPMI k_g auth key */ #endif /* type == HOST */ char *host; /* hostname */ diff --git a/conserver/conserver.man b/conserver/conserver.man index 26dd96b..df68c58 100644 --- a/conserver/conserver.man +++ b/conserver/conserver.man @@ -1,6 +1,6 @@ .\" @(#)conserver.8 01/06/91 OSU CIS; Thomas A. Fine .\" $Id: conserver.man,v 1.54 2006/12/31 02:02:48 bryan Exp $ -.TH CONSERVER 8 "2006/12/31" "conserver-8.1.19" "conserver" +.TH CONSERVER 8 "2006/12/31" "conserver-8.1.20" "conserver" .SH NAME conserver \- console server daemon .SH SYNOPSIS diff --git a/conserver/convert.c b/conserver/convert.c index 7cf3c4c..1a047b4 100644 --- a/conserver/convert.c +++ b/conserver/convert.c @@ -1,5 +1,5 @@ /* - * $Id: convert.c,v 1.12 2006/04/07 15:47:20 bryan Exp $ + * $Id: convert.c,v 1.13 2014/04/02 04:45:32 bryan Exp $ * * Copyright conserver.com, 2000 * @@ -70,7 +70,7 @@ ReadLine2(fp, save, iLine) static char buf[1024]; char *wholeline = (char *)0; char *ret = (char *)0; - int i, buflen, peek, commentCheck = 1, comment = 0; + int i, buflen, peek, commentCheck = 1; static STRING *bufstr = (STRING *)0; static STRING *wholestr = (STRING *)0; @@ -112,7 +112,6 @@ ReadLine2(fp, save, iLine) if (!isspace((int)buf[i])) break; if (buf[i] == '#') { - comment = 1; commentCheck = 0; } else if (buf[i] != '\000') { commentCheck = 0; @@ -123,14 +122,11 @@ ReadLine2(fp, save, iLine) buflen = strlen(buf); if ((buflen >= 1) && (buf[buflen - 1] == '\n')) { (*iLine)++; /* Finally have a whole line */ -/* if (comment == 0 && commentCheck == 0) { */ /* Finish off the chunk without the \n */ buf[buflen - 1] = '\000'; BuildString(buf, bufstr); wholeline = BuildString(bufstr->string, wholestr); -/* }*/ peek = 1; - comment = 0; commentCheck = 1; BuildString((char *)0, bufstr); } else { @@ -142,10 +138,6 @@ ReadLine2(fp, save, iLine) /* If we hit the EOF and weren't peeking ahead * and it's not a comment */ - /* - if (!peek && (ret == (char *)0) && (comment == 0) && - (commentCheck == 0)) { - */ if (!peek && (ret == (char *)0)) { (*iLine)++; wholeline = BuildString(bufstr->string, wholestr); @@ -432,7 +424,6 @@ ReadCfg(pcFile, fp) (unsigned char *)ReadLine2(fp, acInSave, &iLine)) != (unsigned char *)0) { char *pcNext; - char cType; acStart = PruneSpace((char *)acIn); if (acStart[0] == '#') { @@ -478,7 +469,6 @@ ReadCfg(pcFile, fp) printf("\ttrusted %s;\n", pcNext); break; default: - cType = ' '; Error("%s(%d) unknown access key `%s'", pcFile, iLine, acStart); break; diff --git a/conserver/cutil.c b/conserver/cutil.c index ef8827f..e8655cd 100644 --- a/conserver/cutil.c +++ b/conserver/cutil.c @@ -1,5 +1,5 @@ /* - * $Id: cutil.c,v 1.138 2013/09/26 17:50:24 bryan Exp $ + * $Id: cutil.c,v 1.140 2014/04/04 16:17:10 bryan Exp $ * * Copyright conserver.com, 2000 * @@ -540,10 +540,14 @@ FmtCtlStr(pcIn, len, pcOut) { unsigned char c; + BuildString((char *)0, pcOut); + + if (pcIn == (char *)0) + return; + if (len < 0) len = strlen(pcIn); - BuildString((char *)0, pcOut); for (; len; len--, pcIn++) { c = *pcIn & 0xff; if (c > 127) { @@ -1385,15 +1389,19 @@ FileCanRead(cfp, prfd, pwfd) fd_set *pwfd; #endif { +#if HAVE_OPENSSL int fdout; +#endif if (cfp == (CONSFILE *)0) return 0; +#if HAVE_OPENSSL if (cfp->ftype == simplePipe) fdout = cfp->fdout; else fdout = cfp->fd; +#endif return ((FD_ISSET(cfp->fd, prfd) #if HAVE_OPENSSL @@ -2746,7 +2754,11 @@ GetWord(fp, line, spaceok, word) if (c == '\n') { if (fname->used > 0) { while (fname->used > 1 && isspace((int) - (fname->string[fname->used - 2]))) + (fname-> + string + [fname-> + used - + 2]))) fname->used--; if (fname->used > 0) fname->string[fname->used - 1] = '\000'; @@ -3036,8 +3048,8 @@ ParseFile(filename, fp, level) case VALUE: switch (token) { case WORD: - (*sections[secIndex]. - items[keyIndex].reg) (word->string); + (*sections[secIndex].items[keyIndex]. + reg) (word->string); state = SEMI; break; case SEMICOLON: diff --git a/conserver/group.c b/conserver/group.c index 66d734d..87ac302 100644 --- a/conserver/group.c +++ b/conserver/group.c @@ -1,5 +1,5 @@ /* - * $Id: group.c,v 5.344 2013/09/26 17:50:24 bryan Exp $ + * $Id: group.c,v 5.346 2014/04/04 16:17:10 bryan Exp $ * * Copyright conserver.com, 2000 * @@ -207,7 +207,7 @@ AbortAnyClientExec(pCL) } } -static int +void #if PROTOTYPES StopTask(CONSENT *pCE) #else @@ -2085,7 +2085,6 @@ InvokeTask(pCLServing, pCEServing, id) #endif { TASKS *t = (TASKS *)0; - int ret; char *cmd; if ((id < '0' || id > '9') && (id < 'a' || id > 'z')) { @@ -2472,6 +2471,13 @@ CommandExamine(pGE, pCLServing, pCEServing, tyme, args) b = pCE->baud->acrate; p = pCE->parity->key[0]; break; +#if HAVE_FREEIPMI + case IPMI: + d = BuildTmpStringPrint("%s", pCE->host); + b = "IPMI"; + p = ' '; + break; +#endif case HOST: d = BuildTmpStringPrint("%s/%hu", pCE->host, pCE->netport); b = "Netwk"; @@ -2622,8 +2628,8 @@ CommandHosts(pGE, pCLServing, pCEServing, tyme, args) pCE->ioState == ISNORMAL) ? (pCE->initfile == (CONSFILE *) 0 ? "up" : "init") : "down", - pCE->pCLwr ? pCE->pCLwr->acid->string : pCE-> - pCLon ? "" : ""); + pCE->pCLwr ? pCE->pCLwr->acid-> + string : pCE->pCLon ? "" : ""); if (args != (char *)0) break; } @@ -2662,6 +2668,12 @@ CommandInfo(pGE, pCLServing, pCEServing, tyme, args) (unsigned long)pCE->ipid, pCE->execSlave, FileFDNum(pCE->cofile)); break; +#if HAVE_FREEIPMI + case IPMI: + FilePrint(pCLServing->fd, FLAGTRUE, "@:%s,%d:", pCE->host, + FileFDNum(pCE->cofile)); + break; +#endif case HOST: FilePrint(pCLServing->fd, FLAGTRUE, "!:%s,%hu,%s,%d:", pCE->host, pCE->netport, @@ -2734,20 +2746,24 @@ CommandInfo(pGE, pCLServing, pCEServing, tyme, args) } BuildTmpString((char *)0); s = (char *)0; - if (pCE->hupcl == FLAGTRUE) - s = BuildTmpString(",hupcl"); - if (pCE->cstopb == FLAGTRUE) - s = BuildTmpString(",cstopb"); - if (pCE->ixon == FLAGTRUE) - s = BuildTmpString(",ixon"); - if (pCE->ixany == FLAGTRUE) - s = BuildTmpString(",ixany"); - if (pCE->ixoff == FLAGTRUE) - s = BuildTmpString(",ixoff"); + if (pCE->type == DEVICE) { + if (pCE->hupcl == FLAGTRUE) + s = BuildTmpString(",hupcl"); + if (pCE->cstopb == FLAGTRUE) + s = BuildTmpString(",cstopb"); #if defined(CRTSCTS) - if (pCE->crtscts == FLAGTRUE) - s = BuildTmpString(",crtscts"); + if (pCE->crtscts == FLAGTRUE) + s = BuildTmpString(",crtscts"); #endif + } + if (pCE->type == DEVICE || pCE->type == EXEC) { + if (pCE->ixon == FLAGTRUE) + s = BuildTmpString(",ixon"); + if (pCE->ixany == FLAGTRUE) + s = BuildTmpString(",ixany"); + if (pCE->ixoff == FLAGTRUE) + s = BuildTmpString(",ixoff"); + } if (pCE->ondemand == FLAGTRUE) s = BuildTmpString(",ondemand"); if (pCE->reinitoncc == FLAGTRUE) @@ -2919,6 +2935,7 @@ DoConsoleRead(pCEServing) FD_CLR(cofile, &winit); return; } + /* read terminal line */ if ((nr = FileRead(pCEServing->cofile, acInOrig, sizeof(acInOrig))) < 0) { @@ -3121,7 +3138,7 @@ DoTaskRead(pCEServing) #endif { unsigned char acInOrig[BUFSIZ]; - int nr, i, fd; + int nr, fd; CONSCLIENT *pCL; if (pCEServing->taskfile == (CONSFILE *)0) @@ -3303,7 +3320,6 @@ DoClientRead(pGE, pCLServing) CONSCLIENT *pCLServing; #endif { - struct termios sbuf; CONSENT *pCEServing = pCLServing->pCEto; int nr, i, l; unsigned char acIn[BUFSIZ], acInOrig[BUFSIZ]; @@ -3690,8 +3706,9 @@ DoClientRead(pGE, pCLServing) pcArgs, pCLServing->acid->string); num = DisconnectCertainClients(pGE, - pCLServing->acid-> - string, pcArgs); + pCLServing-> + acid->string, + pcArgs); /* client expects this string to be formatted * in this way only. */ @@ -4338,8 +4355,8 @@ DoClientRead(pGE, pCLServing) BumpClient(pCEServing, (char *)0); TagLogfileAct(pCEServing, "%s detached", - pCLServing->acid-> - string); + pCLServing-> + acid->string); FindWrite(pCEServing); } break; @@ -4356,8 +4373,8 @@ DoClientRead(pGE, pCLServing) case '|': /* wait for client */ if (!pCLServing->fwr || ConsentUserOk(pLUList, - pCLServing->username-> - string) == 1) + pCLServing-> + username->string) == 1) goto unknownchar; FileSetQuoteIAC(pCLServing->fd, FLAGFALSE); FilePrint(pCLServing->fd, FLAGFALSE, @@ -5008,68 +5025,101 @@ Kiddie(pGE, sfd) continue; switch (pCEServing->ioState) { case INCONNECT: - /* deal with this state above as well */ - if (FileCanWrite(pCEServing->cofile, &rmask, &wmask)) { - socklen_t slen; - int flags = 0; - int cofile = FileFDNum(pCEServing->cofile); - slen = sizeof(flags); - /* So, getsockopt seems to return -1 if there is - * something interesting in SO_ERROR under - * solaris...sheesh. So, the error message has - * the small change it's not accurate. - */ - if (getsockopt - (cofile, SOL_SOCKET, SO_ERROR, (char *)&flags, - &slen) < 0) { - Error - ("[%s] getsockopt(%u,SO_ERROR): %s: forcing down", - pCEServing->server, cofile, - strerror(errno)); - /* no ConsoleError() for same reason as above */ - SendIWaitClientsMsg(pCEServing, "down]\r\n"); - ConsDown(pCEServing, FLAGTRUE, FLAGTRUE); +#if HAVE_FREEIPMI + if (pCEServing->type == IPMI) { + if (FileCanRead + (pCEServing->cofile, &rmask, &wmask)) { + if (IPMICONSOLE_CTX_STATUS_SOL_ESTABLISHED == + ipmiconsole_ctx_status + (pCEServing->ipmictx)) { + /* Read in the NULL from OUTPUT_ON_SOL_ESTABLISHED flag */ + char b[1]; + FileRead(pCEServing->cofile, b, 1); /* trust it's NULL */ + } else { + Error("[%s] IPMI error: %s: forcing down", + pCEServing->server, + ipmiconsole_ctx_errormsg(pCEServing-> + ipmictx)); + /* no ConsoleError() for same reason as above */ + SendIWaitClientsMsg(pCEServing, + "down]\r\n"); + ConsDown(pCEServing, FLAGTRUE, FLAGTRUE); + break; + } + } else break; - } - if (flags != 0) { - Error("[%s] connect(%u): %s: forcing down", - pCEServing->server, cofile, - strerror(flags)); - /* no ConsoleError() for same reason as above */ - SendIWaitClientsMsg(pCEServing, "down]\r\n"); - ConsDown(pCEServing, FLAGTRUE, FLAGTRUE); + } else { +#endif /* freeipmi */ + /* deal with this state above as well */ + if (FileCanWrite + (pCEServing->cofile, &rmask, &wmask)) { + socklen_t slen; + int flags = 0; + int cofile = FileFDNum(pCEServing->cofile); + slen = sizeof(flags); + /* So, getsockopt seems to return -1 if there is + * something interesting in SO_ERROR under + * solaris...sheesh. So, the error message has + * the small change it's not accurate. + */ + if (getsockopt + (cofile, SOL_SOCKET, SO_ERROR, + (char *)&flags, &slen) < 0) { + Error + ("[%s] getsockopt(%u,SO_ERROR): %s: forcing down", + pCEServing->server, cofile, + strerror(errno)); + /* no ConsoleError() for same reason as above */ + SendIWaitClientsMsg(pCEServing, + "down]\r\n"); + ConsDown(pCEServing, FLAGTRUE, FLAGTRUE); + break; + } + if (flags != 0) { + Error("[%s] connect(%u): %s: forcing down", + pCEServing->server, cofile, + strerror(flags)); + /* no ConsoleError() for same reason as above */ + SendIWaitClientsMsg(pCEServing, + "down]\r\n"); + ConsDown(pCEServing, FLAGTRUE, FLAGTRUE); + break; + } + + /* waiting for a connect(), we watch the write bit, + * so switch around and now watch for the read and + * start gathering data + */ + FD_SET(cofile, &rinit); + FD_CLR(cofile, &winit); + } else break; - } - pCEServing->ioState = ISNORMAL; - pCEServing->lastWrite = time((time_t *)0); -#if HAVE_GETTIMEOFDAY - if (gettimeofday(&tv, (void *)0) == 0) - pCEServing->lastInit = tv; -#else - if ((tv = time((time_t *)0)) != (time_t)-1) - pCEServing->lastInit = tv; -#endif - /* waiting for a connect(), we watch the write bit, - * so switch around and now watch for the read and - * start gathering data - */ - FD_SET(cofile, &rinit); - FD_CLR(cofile, &winit); - if (pCEServing->idletimeout != (time_t)0 && - (timers[T_CIDLE] == (time_t)0 || - timers[T_CIDLE] > - pCEServing->lastWrite + - pCEServing->idletimeout)) - timers[T_CIDLE] = - pCEServing->lastWrite + - pCEServing->idletimeout; - if (pCEServing->downHard == FLAGTRUE) { - Msg("[%s] console up", pCEServing->server); - pCEServing->downHard = FLAGFALSE; - } - SendIWaitClientsMsg(pCEServing, "up]\r\n"); - StartInit(pCEServing); +#if HAVE_FREEIPMI } +#endif + + pCEServing->ioState = ISNORMAL; + pCEServing->lastWrite = time((time_t *)0); +#if HAVE_GETTIMEOFDAY + if (gettimeofday(&tv, (void *)0) == 0) + pCEServing->lastInit = tv; +#else + if ((tv = time((time_t *)0)) != (time_t)-1) + pCEServing->lastInit = tv; +#endif + if (pCEServing->idletimeout != (time_t)0 && + (timers[T_CIDLE] == (time_t)0 || + timers[T_CIDLE] > + pCEServing->lastWrite + pCEServing->idletimeout)) + timers[T_CIDLE] = + pCEServing->lastWrite + + pCEServing->idletimeout; + if (pCEServing->downHard == FLAGTRUE) { + Msg("[%s] console up", pCEServing->server); + pCEServing->downHard = FLAGFALSE; + } + SendIWaitClientsMsg(pCEServing, "up]\r\n"); + StartInit(pCEServing); break; case ISNORMAL: if (FileCanRead(pCEServing->cofile, &rmask, &wmask)) diff --git a/conserver/main.c b/conserver/main.c index 95001d7..a4e5e3b 100644 --- a/conserver/main.c +++ b/conserver/main.c @@ -1,5 +1,5 @@ /* - * $Id: main.c,v 5.208 2013/09/25 22:10:29 bryan Exp $ + * $Id: main.c,v 5.210 2014/04/04 16:17:10 bryan Exp $ * * Copyright conserver.com, 2000 * @@ -658,6 +658,9 @@ Version() #if HAVE_DMALLOC "dmalloc", #endif +#if HAVE_FREEIPMI + "freeipmi", +#endif #if USE_LIBWRAP "libwrap", #endif @@ -728,6 +731,15 @@ Version() #endif Msg("dmalloc version: %s", acA1->string); #endif +#if HAVE_FREEIPMI + BuildString((char *)0, acA1); + BuildStringChar('0' + LIBIPMICONSOLE_VERSION_MAJOR, acA1); + BuildStringChar('.', acA1); + BuildStringChar('0' + LIBIPMICONSOLE_VERSION_MINOR, acA1); + BuildStringChar('.', acA1); + BuildStringChar('0' + LIBIPMICONSOLE_VERSION_PATCH, acA1); + Msg("freeipmi version: %s", acA1->string); +#endif #if HAVE_OPENSSL Msg("openssl version: %s", OPENSSL_VERSION_TEXT); #endif @@ -854,6 +866,12 @@ SummarizeDataStructures() size += strlen(pCE->tasklist); if (pCE->breaklist != (char *)0) size += strlen(pCE->breaklist); +#if HAVE_FREEIPMI + if (pCE->username != (char *)0) + size += strlen(pCE->username); + if (pCE->password != (char *)0) + size += strlen(pCE->password); +#endif if (pCE->fdlog != (CONSFILE *)0) size += sizeof(CONSFILE); if (pCE->cofile != (CONSFILE *)0) @@ -936,6 +954,11 @@ DumpDataStructures() REMOTE *pRC; int i; TASKS *t; +#if HAVE_FREEIPMI + static STRING *tmpString = (STRING *)0; + if (tmpString == (STRING *)0) + tmpString = AllocString(); +#endif #if HAVE_DMALLOC && DMALLOC_MARK_MAIN CONDDEBUG((1, "DumpDataStructures(): dmalloc / MarkMain")); @@ -979,6 +1002,27 @@ DumpDataStructures() pCE->execuid, pCE->execgid)); break; +#if HAVE_FREEIPMI + case IPMI: + CONDDEBUG((1, + "DumpDataStructures(): server=%s, type=IPMI", + EMPTYSTR(pCE->server))); + CONDDEBUG((1, + "DumpDataStructures(): host=%s, username=%s, password=%s, ipmiprivlevel=%d", + EMPTYSTR(pCE->host), + EMPTYSTR(pCE->username), + EMPTYSTR(pCE->password), + pCE->ipmiprivlevel)); + CONDDEBUG((1, + "DumpDataStructures(): ipmiwrkset=%d, ipmiworkaround=%u, ipmiciphersuite=%d", + pCE->ipmiwrkset, pCE->ipmiworkaround, + pCE->ipmiciphersuite)); + FmtCtlStr(pCE->ipmikg->string, pCE->ipmikg->used - 1, + tmpString); + CONDDEBUG((1, "DumpDataStructures(): ipmikg=%s", + EMPTYSTR(tmpString->string))); + break; +#endif case HOST: CONDDEBUG((1, "DumpDataStructures(): server=%s, type=HOST", diff --git a/conserver/readcfg.c b/conserver/readcfg.c index 2936065..cd9416e 100644 --- a/conserver/readcfg.c +++ b/conserver/readcfg.c @@ -1,5 +1,5 @@ /* - * $Id: readcfg.c,v 5.202 2013/09/26 17:50:24 bryan Exp $ + * $Id: readcfg.c,v 5.204 2014/04/04 16:17:10 bryan Exp $ * * Copyright conserver.com, 2000 * @@ -316,9 +316,9 @@ BreakDestroy() for (i = 0; i < 9; i++) { Msg("Break[%d] = `%s', delay=%d", i, breakList[i].seq == - (STRING *)0 ? "(null)" : (breakList[i].seq-> - string ? breakList[i].seq-> - string : "(null)"), + (STRING *)0 ? "(null)" : (breakList[i]. + seq->string ? breakList[i]. + seq->string : "(null)"), breakList[i].delay); } } @@ -680,6 +680,14 @@ DestroyParserDefaultOrConsole(c, ph, pt) free(c->breaklist); if (c->execSlave != (char *)0) free(c->execSlave); +#if HAVE_FREEIPMI + if (c->username != (char *)0) + free(c->username); + if (c->password != (char *)0) + free(c->password); + if (c->ipmikg != (STRING *)0) + DestroyString(c->ipmikg); +#endif while (c->aliases != (NAMES *)0) { NAMES *name; name = c->aliases->next; @@ -884,6 +892,35 @@ ApplyDefault(d, c) if ((c->breaklist = StrDup(d->breaklist)) == (char *)0) OutOfMem(); } +#if HAVE_FREEIPMI + if (d->ipmiwrkset != 0) { + c->ipmiworkaround = d->ipmiworkaround; + c->ipmiwrkset = d->ipmiwrkset; + } + if (d->ipmiciphersuite != 0) + c->ipmiciphersuite = d->ipmiciphersuite; + if (d->ipmiprivlevel != IPMIL_UNKNOWN) + c->ipmiprivlevel = d->ipmiprivlevel; + if (d->username != (char *)0) { + if (c->username != (char *)0) + free(c->username); + if ((c->username = StrDup(d->username)) == (char *)0) + OutOfMem(); + } + if (d->password != (char *)0) { + if (c->password != (char *)0) + free(c->password); + if ((c->password = StrDup(d->password)) == (char *)0) + OutOfMem(); + } + if (d->ipmikg != (STRING *)0) { + if (c->ipmikg != (STRING *)0) + BuildString((char *)0, c->ipmikg); + else + c->ipmikg = AllocString(); + BuildStringN(d->ipmikg->string, d->ipmikg->used - 1, c->ipmikg); + } +#endif CopyConsentUserList(d->ro, &(c->ro), 0); CopyConsentUserList(d->rw, &(c->rw), 0); } @@ -1360,6 +1397,39 @@ DefaultItemInitrunas(id) ProcessInitrunas(parserDefaultTemp, id); } +#if HAVE_FREEIPMI +void +#if PROTOTYPES +ProcessIpmiPrivLevel(CONSENT *c, char *id) +#else +ProcessIpmiPrivLevel(c, id) + CONSENT *c; + char *id; +#endif +{ + if (!strcasecmp("user", id)) + c->ipmiprivlevel = IPMIL_USER; + else if (!strcasecmp("operator", id)) + c->ipmiprivlevel = IPMIL_OPERATOR; + else if (!strcasecmp("admin", id)) + c->ipmiprivlevel = IPMIL_ADMIN; + else + Error("invalid ipmiprivlevel `%s' [%s:%d]", id, file, line); +} + +void +#if PROTOTYPES +DefaultItemIpmiPrivLevel(char *id) +#else +DefaultItemIpmiPrivLevel(id) + char *id; +#endif +{ + CONDDEBUG((1, "DefaultItemIpmiPrivLevel(%s) [%s:%d]", id, file, line)); + ProcessIpmiPrivLevel(parserDefaultTemp, id); +} +#endif /*freeipmi */ + void #if PROTOTYPES DefaultItemExecrunas(char *id) @@ -1494,6 +1564,311 @@ DefaultItemUds(id) ProcessUds(parserDefaultTemp, id); } +#if HAVE_FREEIPMI +void +#if PROTOTYPES +ProcessIpmiKG(CONSENT *c, char *id) +#else +ProcessIpmiKG(c, id) + CONSENT *c; + char *id; +#endif +{ + char s; + char oct = '\000'; + short octs = 0; + short backslash = 0; + char *i = id; + static STRING *t = (STRING *)0; + + if (t == (STRING *)0) + t = AllocString(); + + if ((id == (char *)0) || (*id == '\000')) { + if (c->ipmikg != (STRING *)0) { + DestroyString(c->ipmikg); + c->ipmikg = (STRING *)0; + } + return; + } + + BuildString((char *)0, t); + + while ((s = (*i++)) != '\000') { + if (octs > 0 && octs < 3 && s >= '0' && s <= '7') { + ++octs; + oct = oct * 8 + (s - '0'); + continue; + } + if (octs != 0) { + BuildStringChar(oct, t); + octs = 0; + oct = '\000'; + } + if (backslash) { + backslash = 0; + if (s >= '0' && s <= '7') { + ++octs; + oct = oct * 8 + (s - '0'); + continue; + } + BuildStringChar(s, t); + continue; + } + if (s == '\\') { + backslash = 1; + continue; + } + BuildStringChar(s, t); + } + + if (octs != 0) + BuildStringChar(oct, t); + + if (backslash) + BuildStringChar('\\', t); + + if (t->used > 21) { /* max 20 chars */ + if (isMaster) + Error("ipmikg string `%s' over 20 characters [%s:%d]", id, + file, line); + return; + } + if (!ipmiconsole_k_g_is_valid((unsigned char *)t->string, t->used - 1)) { + if (isMaster) + Error("invalid ipmikg string `%s' [%s:%d]", id, file, line); + return; + } + + if (c->ipmikg == (STRING *)0) + c->ipmikg = AllocString(); + BuildString((char *)0, c->ipmikg); + BuildStringN(t->string, t->used - 1, c->ipmikg); +} + +void +#if PROTOTYPES +DefaultItemIpmiKG(char *id) +#else +DefaultItemIpmiKG(id) + char *id; +#endif +{ + CONDDEBUG((1, "DefaultItemIpmiKG(%s) [%s:%d]", id, file, line)); + ProcessIpmiKG(parserDefaultTemp, 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 +ProcessIpmiCipherSuite(CONSENT *c, char *id) +#else +ProcessIpmiCipherSuite(c, id) + CONSENT *c; + char *id; +#endif +{ + char *p; + int i; + + if ((id == (char *)0) || (*id == '\000')) { + c->ipmiciphersuite = 0; + return; + } + + /* if we have -1, allow it (we allow >= -1 now) */ + if (id[0] == '-' && id[1] == '1' && id[2] == '\000') { + c->ipmiciphersuite = 1; + return; + } + + for (p = id; *p != '\000'; p++) + if (!isdigit((int)(*p))) + break; + + /* if it wasn't a number */ + if (*p != '\000') { + if (isMaster) + Error("invalid ipmiciphersuite number `%s' [%s:%d]", id, file, + line); + return; + } + + i = atoi(id); + + if (ipmiconsole_cipher_suite_id_is_valid(i)) + c->ipmiciphersuite = i + 2; + else { + if (isMaster) + Error("invalid ipmiciphersuite number `%s' [%s:%d]", id, file, + line); + return; + } +} + +void +#if PROTOTYPES +DefaultItemIpmiCipherSuite(char *id) +#else +DefaultItemIpmiCipherSuite(id) + char *id; +#endif +{ + CONDDEBUG((1, "DefaultItemIpmiCipherSuite(%s) [%s:%d]", id, file, + line)); + ProcessIpmiCipherSuite(parserDefaultTemp, id); +} + +void +#if PROTOTYPES +ProcessIpmiWorkaround(CONSENT *c, char *id) +#else +ProcessIpmiWorkaround(c, id) + CONSENT *c; + char *id; +#endif +{ + unsigned int flag; + char *token = (char *)0; + short valid = 0; + unsigned int wrk = 0; + + if ((id == (char *)0) || (*id == '\000')) { + c->ipmiworkaround = 0; + c->ipmiwrkset = 1; + return; + } + + for (token = strtok(id, ALLWORDSEP); token != (char *)0; + token = strtok(NULL, ALLWORDSEP)) { + short not; + if (token[0] == '!') { + token++; + not = 1; + } else + not = 0; + if (!strcmp(token, "default")) + flag = IPMICONSOLE_WORKAROUND_DEFAULT; +#if defined(IPMICONSOLE_WORKAROUND_AUTHENTICATION_CAPABILITIES) + else if (!strcmp(token, "auth-capabilites")) + flag = IPMICONSOLE_WORKAROUND_AUTHENTICATION_CAPABILITIES; +#endif +#if defined(IPMICONSOLE_WORKAROUND_INTEL_2_0_SESSION) + else if (!strcmp(token, "intel-session")) + flag = IPMICONSOLE_WORKAROUND_INTEL_2_0_SESSION; +#endif +#if defined(IPMICONSOLE_WORKAROUND_SUPERMICRO_2_0_SESSION) + else if (!strcmp(token, "supermicro-session")) + flag = IPMICONSOLE_WORKAROUND_SUPERMICRO_2_0_SESSION; +#endif +#if defined(IPMICONSOLE_WORKAROUND_SUN_2_0_SESSION) + else if (!strcmp(token, "sun-session")) + flag = IPMICONSOLE_WORKAROUND_SUN_2_0_SESSION; +#endif +#if defined(IPMICONSOLE_WORKAROUND_OPEN_SESSION_PRIVILEGE) + else if (!strcmp(token, "privilege")) + flag = IPMICONSOLE_WORKAROUND_OPEN_SESSION_PRIVILEGE; +#endif +#if defined(IPMICONSOLE_WORKAROUND_NON_EMPTY_INTEGRITY_CHECK_VALUE) + else if (!strcmp(token, "integrity")) + flag = IPMICONSOLE_WORKAROUND_NON_EMPTY_INTEGRITY_CHECK_VALUE; +#endif +#if defined(IPMICONSOLE_WORKAROUND_NO_CHECKSUM_CHECK) + else if (!strcmp(token, "checksum")) + flag = IPMICONSOLE_WORKAROUND_NO_CHECKSUM_CHECK; +#endif +#if defined(IPMICONSOLE_WORKAROUND_SERIAL_ALERTS_DEFERRED) + else if (!strcmp(token, "serial-alerts")) + flag = IPMICONSOLE_WORKAROUND_SERIAL_ALERTS_DEFERRED; +#endif +#if defined(IPMICONSOLE_WORKAROUND_INCREMENT_SOL_PACKET_SEQUENCE) + else if (!strcmp(token, "packet-sequence")) + flag = IPMICONSOLE_WORKAROUND_INCREMENT_SOL_PACKET_SEQUENCE; +#endif +#if defined(IPMICONSOLE_WORKAROUND_IGNORE_SOL_PAYLOAD_SIZE) + else if (!strcmp(token, "ignore-payload-size")) + flag = IPMICONSOLE_WORKAROUND_IGNORE_SOL_PAYLOAD_SIZE; +#endif +#if defined(IPMICONSOLE_WORKAROUND_IGNORE_SOL_PORT) + else if (!strcmp(token, "ignore-port")) + flag = IPMICONSOLE_WORKAROUND_IGNORE_SOL_PORT; +#endif +#if defined(IPMICONSOLE_WORKAROUND_SKIP_SOL_ACTIVATION_STATUS) + else if (!strcmp(token, "activation-status")) + flag = IPMICONSOLE_WORKAROUND_SKIP_SOL_ACTIVATION_STATUS; +#endif +#if defined(IPMICONSOLE_WORKAROUND_SKIP_CHANNEL_PAYLOAD_SUPPORT) + else if (!strcmp(token, "channel-payload")) + flag = IPMICONSOLE_WORKAROUND_SKIP_CHANNEL_PAYLOAD_SUPPORT; +#endif + else { + if (isMaster) + Error("invalid ipmiworkaround `%s' [%s:%d]", token, file, + line); + continue; + } + if (not) { + wrk &= ~flag; + } else { + wrk |= flag; + } + valid = 1; + } + + if (valid) { + if (ipmiconsole_workaround_flags_is_valid(wrk)) { + c->ipmiworkaround = wrk; + c->ipmiwrkset = 1; + } else { + if (isMaster) + Error("invalid ipmiworkaround setting [%s:%d]", file, + line); + return; + } + } +} + +void +#if PROTOTYPES +DefaultItemIpmiWorkaround(char *id) +#else +DefaultItemIpmiWorkaround(id) + char *id; +#endif +{ + CONDDEBUG((1, "DefaultItemIpmiWorkaround(%s) [%s:%d]", id, file, + line)); + ProcessIpmiWorkaround(parserDefaultTemp, id); +} +#endif /*freeipmi */ + void #if PROTOTYPES ProcessInclude(CONSENT *c, char *id) @@ -1863,6 +2238,36 @@ DefaultItemParity(id) ProcessParity(parserDefaultTemp, id); } +#if HAVE_FREEIPMI +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); +} +#endif /*freeipmi */ + void #if PROTOTYPES ProcessPort(CONSENT *c, char *id) @@ -2550,6 +2955,10 @@ ProcessType(c, id) } if (strcasecmp("device", id) == 0) t = DEVICE; +#if HAVE_FREEIPMI + else if (strcasecmp("ipmi", id) == 0) + t = IPMI; +#endif else if (strcasecmp("exec", id) == 0) t = EXEC; else if (strcasecmp("host", id) == 0) @@ -2713,6 +3122,16 @@ ConsoleEnd() } } break; +#if HAVE_FREEIPMI + case IPMI: + if (parserConsoleTemp->host == (char *)0) { + if (isMaster) + Error("[%s] console missing 'host' attribute [%s:%d]", + parserConsoleTemp->server, file, line); + invalid = 1; + } + break; +#endif case HOST: if (parserConsoleTemp->host == (char *)0) { if (isMaster) @@ -2745,8 +3164,9 @@ 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; } @@ -3088,6 +3508,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); @@ -3222,6 +3643,78 @@ ConsoleAdd(c) } #endif break; +#if HAVE_FREEIPMI + 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; + } + if (pCEmatch->username != (char *)0 && + c->username != (char *)0) { + if (strcmp(pCEmatch->username, c->username) != 0) { + SwapStr(&pCEmatch->username, &c->username); + closeMatch = 0; + } + } else if (pCEmatch->username != (char *)0 || + c->username != (char *)0) { + SwapStr(&pCEmatch->username, &c->username); + closeMatch = 0; + } + if (pCEmatch->password != (char *)0 && + c->password != (char *)0) { + if (strcmp(pCEmatch->password, c->password) != 0) { + SwapStr(&pCEmatch->password, &c->password); + closeMatch = 0; + } + } else if (pCEmatch->password != (char *)0 || + c->password != (char *)0) { + SwapStr(&pCEmatch->password, &c->password); + closeMatch = 0; + } + if (pCEmatch->ipmiprivlevel != c->ipmiprivlevel) { + pCEmatch->ipmiprivlevel = c->ipmiprivlevel; + closeMatch = 0; + } + if (pCEmatch->ipmiworkaround != c->ipmiworkaround) { + pCEmatch->ipmiworkaround = c->ipmiworkaround; + closeMatch = 0; + } + if (pCEmatch->ipmiciphersuite != c->ipmiciphersuite) { + pCEmatch->ipmiciphersuite = c->ipmiciphersuite; + closeMatch = 0; + } + if (pCEmatch->ipmikg->used != 0 && + c->ipmikg->used == pCEmatch->ipmikg->used) { + if ( +#if HAVE_MEMCMP + memcmp(pCEmatch->ipmikg->string, c->ipmikg, + c->ipmikg->used) != 0 +#else + bcmp(pCEmatch->ipmikg->string, c->ipmikg, + c->ipmikg->used) != 0 +#endif + ) { + BuildString((char *)0, pCEmatch->ipmikg); + BuildStringN(c->ipmikg->string, + c->ipmikg->used - 1, + pCEmatch->ipmikg); + closeMatch = 0; + } + } else if (pCEmatch->ipmikg->used != 0 || + c->ipmikg->used != 0) { + BuildString((char *)0, pCEmatch->ipmikg); + BuildStringN(c->ipmikg->string, c->ipmikg->used - 1, + pCEmatch->ipmikg); + closeMatch = 0; + } + break; +#endif /* freeipmi */ case HOST: if (pCEmatch->host != (char *)0 && c->host != (char *)0) { if (strcasecmp(pCEmatch->host, c->host) != 0) { @@ -3361,6 +3854,24 @@ ConsoleDestroy() for (c = parserConsoles; c != (CONSENT *)0; c = cNext) { /* time to set some defaults and fix up values */ +#if HAVE_FREEIPMI + if (c->ipmiprivlevel == 0) + c->ipmiprivlevel = IPMIL_ADMIN; + c->ipmiprivlevel--; + + if (c->ipmiciphersuite == 0) + c->ipmiciphersuite = 1; + c->ipmiciphersuite -= 2; + + if (c->ipmikg == (STRING *)0) + c->ipmikg = AllocString(); + + if (c->ipmiwrkset == 0) { + c->ipmiworkaround = IPMICONSOLE_WORKAROUND_DEFAULT; + c->ipmiwrkset = 1; + } +#endif + /* default break number */ if (c->breakNum == 0) c->breakNum = 1; @@ -3559,6 +4070,10 @@ ConsoleDestroy() (c->parity ? c->parity->key[0] : ' ')), s); break; +#if HAVE_FREEIPMI + case IPMI: + BuildString(BuildTmpStringPrint("@:%s", c->host), s); +#endif case UNKNOWNTYPE: /* shut up gcc */ break; } @@ -3872,6 +4387,58 @@ ConsoleItemUds(id) ProcessUds(parserConsoleTemp, id); } +#if HAVE_FREEIPMI +void +#if PROTOTYPES +ConsoleItemIpmiKG(char *id) +#else +ConsoleItemIpmiKG(id) + char *id; +#endif +{ + CONDDEBUG((1, "ConsoleItemIpmiKG(%s) [%s:%d]", id, file, line)); + ProcessIpmiKG(parserConsoleTemp, 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 +ConsoleItemIpmiCipherSuite(char *id) +#else +ConsoleItemIpmiCipherSuite(id) + char *id; +#endif +{ + CONDDEBUG((1, "ConsoleItemIpmiCipherSuite(%s) [%s:%d]", id, file, + line)); + ProcessIpmiCipherSuite(parserConsoleTemp, id); +} + +void +#if PROTOTYPES +ConsoleItemIpmiWorkaround(char *id) +#else +ConsoleItemIpmiWorkaround(id) + char *id; +#endif +{ + CONDDEBUG((1, "ConsoleItemIpmiWorkaround(%s) [%s:%d]", id, file, + line)); + ProcessIpmiWorkaround(parserConsoleTemp, id); +} +#endif /*freeipmi */ + void #if PROTOTYPES ConsoleItemInclude(char *id) @@ -3980,6 +4547,20 @@ ConsoleItemParity(id) ProcessParity(parserConsoleTemp, id); } +#if HAVE_FREEIPMI +void +#if PROTOTYPES +ConsoleItemPassword(char *id) +#else +ConsoleItemPassword(id) + char *id; +#endif +{ + CONDDEBUG((1, "ConsoleItemPassword(%s) [%s:%d]", id, file, line)); + ProcessPassword(parserConsoleTemp, id); +} +#endif /*freeipmi */ + void #if PROTOTYPES ConsoleItemPort(char *id) @@ -4484,9 +5065,10 @@ AccessProcessACL(trust, acl) char *token = (char *)0; ACCESS **ppa = (ACCESS **)0; ACCESS *pa = (ACCESS *)0; - in_addr_t addr; #if HAVE_INET_ATON struct in_addr inetaddr; +#else + in_addr_t addr; #endif /* an empty acl will clear out that type of acl */ @@ -4544,7 +5126,6 @@ AccessProcessACL(trust, acl) #if HAVE_INET_ATON if (inet_aton(token, &inetaddr) == 0) goto cidrerror; - addr = inetaddr.s_addr; #else addr = inet_addr(token); if (addr == (in_addr_t) (-1)) @@ -4827,6 +5408,20 @@ ConfigItemDefaultaccess(id) } } +#if HAVE_FREEIPMI +void +#if PROTOTYPES +ConsoleItemIpmiPrivLevel(char *id) +#else +ConsoleItemIpmiPrivLevel(id) + char *id; +#endif +{ + CONDDEBUG((1, "ConsoleItemIpmiPrivLevel(%s) [%s:%d]", id, file, line)); + ProcessIpmiPrivLevel(parserConsoleTemp, id); +} +#endif /*freeipmi */ + void #if PROTOTYPES ConfigItemAutocomplete(char *id) @@ -5388,6 +5983,14 @@ ITEM keyDefault[] = { {"type", DefaultItemType}, {"uds", DefaultItemUds}, {"udssubst", DefaultItemUdssubst}, +#if HAVE_FREEIPMI + {"ipmiciphersuite", DefaultItemIpmiCipherSuite}, + {"ipmikg", DefaultItemIpmiKG}, + {"ipmiprivlevel", DefaultItemIpmiPrivLevel}, + {"ipmiworkaround", DefaultItemIpmiWorkaround}, + {"password", DefaultItemPassword}, + {"username", DefaultItemUsername}, +#endif {(char *)0, (void *)0} }; @@ -5429,6 +6032,14 @@ ITEM keyConsole[] = { {"type", ConsoleItemType}, {"uds", ConsoleItemUds}, {"udssubst", ConsoleItemUdssubst}, +#if HAVE_FREEIPMI + {"ipmiciphersuite", ConsoleItemIpmiCipherSuite}, + {"ipmikg", ConsoleItemIpmiKG}, + {"ipmiprivlevel", ConsoleItemIpmiPrivLevel}, + {"ipmiworkaround", ConsoleItemIpmiWorkaround}, + {"password", ConsoleItemPassword}, + {"username", ConsoleItemUsername}, +#endif {(char *)0, (void *)0} }; diff --git a/conserver/version.h b/conserver/version.h index 6ca92f2..2c6d595 100644 --- a/conserver/version.h +++ b/conserver/version.h @@ -1,5 +1,5 @@ /* - * $Id: version.h,v 1.78 2013/09/13 20:54:09 bryan Exp $ + * $Id: version.h,v 1.79 2014/04/02 04:45:32 bryan Exp $ * * Copyright conserver.com, 2000 * @@ -16,6 +16,6 @@ All rights reserved.\n" #define VERSION_MAJOR 8 #define VERSION_MINOR 1 -#define VERSION_REV 19 +#define VERSION_REV 20 #define VERSION_TEXT "conserver.com version" #define VERSION_UINT (VERSION_MAJOR * 1000000 + VERSION_MINOR * 1000 + VERSION_REV) diff --git a/console/console.c b/console/console.c index db3a0ef..9e72cf2 100644 --- a/console/console.c +++ b/console/console.c @@ -1,5 +1,5 @@ /* - * $Id: console.c,v 5.188 2013/09/18 14:31:39 bryan Exp $ + * $Id: console.c,v 5.189 2014/04/02 00:02:47 bryan Exp $ * * Copyright conserver.com, 2000 * @@ -376,9 +376,6 @@ Version() #if HAVE_GSSAPI "gssapi", #endif -#if HAVE_PAM - "pam", -#endif #if USE_UNIX_DOMAIN_SOCKETS "uds", #endif @@ -392,12 +389,12 @@ Version() Msg(MyVersion()); #if USE_UNIX_DOMAIN_SOCKETS - Msg("default socket directory `%s\'", UDSDIR); + Msg("default socket directory `%s'", UDSDIR); #else - Msg("default initial master server `%s\'", MASTERHOST); + Msg("default initial master server `%s'", MASTERHOST); Msg("default port referenced as `%s'", DEFPORT); #endif - Msg("default escape sequence `%s%s\'", FmtCtl(DEFATTN, acA1), + Msg("default escape sequence `%s%s'", FmtCtl(DEFATTN, acA1), FmtCtl(DEFESC, acA2)); Msg("default site-wide configuration in `%s'", CLIENTCONFIGFILE); Msg("default per-user configuration in `%s'", "$HOME/.consolerc"); diff --git a/console/console.man b/console/console.man index 21873a9..7cbf4d6 100644 --- a/console/console.man +++ b/console/console.man @@ -1,5 +1,5 @@ .\" $Id: console.man,v 1.65 2013/09/25 22:10:30 bryan Exp $ -.TH CONSOLE 1 "2013/09/25" "conserver-8.1.19" "conserver" +.TH CONSOLE 1 "2013/09/25" "conserver-8.1.20" "conserver" .SH NAME console \- console server client program .SH SYNOPSIS diff --git a/contrib/redhat-rpm/conserver.spec b/contrib/redhat-rpm/conserver.spec index 7cd4b99..8ff5273 100644 --- a/contrib/redhat-rpm/conserver.spec +++ b/contrib/redhat-rpm/conserver.spec @@ -4,7 +4,7 @@ # %define pkg conserver -%define ver 8.1.19 +%define ver 8.1.20 # define the name of the machine on which the main conserver # daemon will be running if you don't want to use the default @@ -16,10 +16,11 @@ # compile arguments. defaults to 0 # example: rpmbuild -bb conserver.spec --with openssl -%define with_openssl %{?_with_openssl: 1} %{?!_with_openssl: 0} -%define with_libwrap %{?_with_libwrap: 1} %{?!_with_libwrap: 0} -%define with_pam %{?_with_pam: 1} %{?!_with_pam: 0} -%define with_dmalloc %{?_with_dmalloc: 1} %{?!_with_dmalloc: 0} +%define with_openssl %{?_with_openssl: 1} %{?!_with_openssl: 0} +%define with_libwrap %{?_with_libwrap: 1} %{?!_with_libwrap: 0} +%define with_pam %{?_with_pam: 1} %{?!_with_pam: 0} +%define with_dmalloc %{?_with_dmalloc: 1} %{?!_with_dmalloc: 0} +%define with_freeipmi %{?_with_freeipmi: 1} %{?!_with_freeipmi: 0} # additionally you can use macros logfile pidfile # example: rpmbuild -bb conserver.spec --define "pidfile /var/run/conserver/pid" @@ -34,6 +35,7 @@ URL: http://www.conserver.com/ Source: http://www.conserver.com/%{pkg}-%{ver}.tar.gz BuildRoot: %{_tmppath}/%{pkg}-buildroot %if %{with_openssl} +Requires: openssl BuildRequires: openssl-devel %endif %if %{with_pam} @@ -46,6 +48,10 @@ Requires: tcp_wrappers Requires: dmalloc BuildRequires: dmalloc %endif +%if %{with_freeipmi} +Requires: freeipmi +BuildRequires: freeipmi-devel +%endif Prefix: %{_prefix} %package server @@ -83,7 +89,7 @@ f="conserver/Makefile.in" %{__mv} $f $f.orig %{__sed} -e 's/^.*conserver\.rc.*$//' < $f.orig > $f -%configure %{?_with_openssl} %{?_with_libwrap} %{?_with_dmalloc} %{?_with_pam} %{?logfile: --with-logfile=%{logfile}} %{?pidfile: --with-pidfile=%{pidfile}} %{?master: --with-master=%{master}} +%configure %{?_with_openssl} %{?_with_libwrap} %{?_with_dmalloc} %{?_with_freeipmi} %{?_with_pam} %{?logfile: --with-logfile=%{logfile}} %{?pidfile: --with-pidfile=%{pidfile}} %{?master: --with-master=%{master}} make diff --git a/contrib/solaris-package/pkginfo b/contrib/solaris-package/pkginfo index 0bb43fe..9a2f79d 100644 --- a/contrib/solaris-package/pkginfo +++ b/contrib/solaris-package/pkginfo @@ -1,7 +1,7 @@ PKG="conserver" NAME="Console server and client" CATEGORY="system" -VERSION="8.1.19" +VERSION="8.1.20" DESC="Console server and client" CLASSES=none ARCH=sparc