From 520fc416dd2f7742dd51b2efb5e42d3233f47d5d Mon Sep 17 00:00:00 2001 From: Adam Tkac Date: Thu, 2 Sep 2010 14:13:24 +0000 Subject: [PATCH] [Development] Implement *Plain security types on the server side and use PAM for credential validation on UNIX. git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@4128 3789f03b-4d11-0410-bbf8-ca57d06f2519 --- common/rfb/Makefile.am | 5 +++ common/rfb/SSecurityPlain.cxx | 65 ++++++++++++++++++++--------------- common/rfb/SSecurityPlain.h | 15 ++++---- common/rfb/Security.cxx | 6 ++++ configure.ac | 6 ++++ 5 files changed, 63 insertions(+), 34 deletions(-) diff --git a/common/rfb/Makefile.am b/common/rfb/Makefile.am index 4e5bbd7f..9251e2fc 100644 --- a/common/rfb/Makefile.am +++ b/common/rfb/Makefile.am @@ -55,6 +55,11 @@ endif librfb_la_CPPFLAGS = -I$(top_srcdir)/common -I$(top_srcdir)/win librfb_la_LIBADD = @GNUTLS_LIBS@ +if HAVE_PAM +librfb_la_SOURCES += UnixPasswordValidator.cxx UnixPasswordValidator.h pam.c pam.h +librfb_la_LIBADD += $(PAM_LIBS) +endif + if INCLUDED_JPEG librfb_la_CPPFLAGS += -I$(top_srcdir)/common/jpeg -I$(top_builddir)/common/jpeg librfb_la_LIBADD += $(top_builddir)/common/jpeg/libjpeg.la diff --git a/common/rfb/SSecurityPlain.cxx b/common/rfb/SSecurityPlain.cxx index 6d0c67e9..84ef0997 100644 --- a/common/rfb/SSecurityPlain.cxx +++ b/common/rfb/SSecurityPlain.cxx @@ -25,6 +25,9 @@ #include #include #include +#ifdef HAVE_PAM +#include +#endif using namespace rfb; @@ -36,27 +39,33 @@ StringParameter PasswordValidator::plainUsers bool PasswordValidator::validUser(const char* username) { CharArray users(strDup(plainUsers.getValueStr())), user; + while (users.buf) { strSplit(users.buf, ',', &user.buf, &users.buf); #ifdef WIN32 - if(0==stricmp(user.buf, "*")) + if (0 == stricmp(user.buf, "*")) return true; - if(0==stricmp(user.buf, username)) + if (0 == stricmp(user.buf, username)) return true; #else - if(!strcmp (user.buf, "*")) + if (!strcmp(user.buf, "*")) return true; - if(!strcmp (user.buf, username)) + if (!strcmp(user.buf, username)) return true; #endif } return false; } -SSecurityPlain::SSecurityPlain(PasswordValidator* _valid) +SSecurityPlain::SSecurityPlain() { - valid=_valid; - state=0; +#ifdef HAVE_PAM + valid = new UnixPasswordValidator(); +#else + valid = NULL; +#endif + + state = 0; } bool SSecurityPlain::processMsg(SConnection* sc) @@ -66,32 +75,34 @@ bool SSecurityPlain::processMsg(SConnection* sc) char *uname; CharArray password; - if(state==0) - { - if(!is->checkNoWait(8)) + if (!valid) + throw AuthFailureException("No password validator configured"); + + if (state == 0) { + if (!is->checkNoWait(8)) return false; - ulen=is->readU32(); - plen=is->readU32(); - state=1; + ulen = is->readU32(); + plen = is->readU32(); + state = 1; } - if(state==1) - { - if(is->checkNoWait(ulen+plen+2)) + + if (state == 1) { + if (is->checkNoWait(ulen + plen + 2)) return false; - state=2; - pw=new char[plen+1]; - uname=new char[ulen+1]; + state = 2; + pw = new char[plen + 1]; + uname = new char[ulen + 1]; username.replaceBuf(uname); password.replaceBuf(pw); - is->readBytes(uname,ulen); - is->readBytes(pw,plen); - pw[plen]=0; - uname[ulen]=0; - plen=0; - if(!valid->validate(sc,uname,pw)) - throw AuthFailureException("invalid password or username"); - return true; + is->readBytes(uname, ulen); + is->readBytes(pw, plen); + pw[plen] = 0; + uname[ulen] = 0; + plen = 0; + if (!valid->validate(sc, uname, pw)) + throw AuthFailureException("invalid password or username"); } + return true; } diff --git a/common/rfb/SSecurityPlain.h b/common/rfb/SSecurityPlain.h index f170bd5b..080fcd59 100644 --- a/common/rfb/SSecurityPlain.h +++ b/common/rfb/SSecurityPlain.h @@ -34,24 +34,25 @@ namespace rfb { class PasswordValidator { public: - // validate username / password combination - bool validate(SConnection* sc, const char *username, const char *password) { return validUser(username) ? validateInternal(sc, username, password) : false; }; - static StringParameter plainUsers; + bool validate(SConnection* sc, const char *username, const char *password) + { return validUser(username) ? validateInternal(sc, username, password) : false; } + static StringParameter plainUsers; + protected: virtual bool validateInternal(SConnection* sc, const char *username, const char *password)=0; - static bool validUser(const char* username); + static bool validUser(const char* username); }; class SSecurityPlain : public SSecurity { public: - SSecurityPlain(PasswordValidator* valid); + SSecurityPlain(); virtual bool processMsg(SConnection* sc); - virtual int getType() const {return secTypePlain;}; + virtual int getType() const { return secTypePlain; }; virtual const char* getUserName() const { return username.buf; } private: PasswordValidator* valid; - unsigned int ulen,plen,state; + unsigned int ulen, plen, state; CharArray username; }; diff --git a/common/rfb/Security.cxx b/common/rfb/Security.cxx index 874c346f..2ea51fac 100644 --- a/common/rfb/Security.cxx +++ b/common/rfb/Security.cxx @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #ifdef HAVE_GNUTLS @@ -146,15 +147,20 @@ SSecurity* Security::GetSSecurity(U32 secType) case secTypeNone: return new SSecurityNone(); case secTypeVncAuth: return new SSecurityVncAuth(); case secTypeVeNCrypt: return new SSecurityVeNCrypt(this); + case secTypePlain: return new SSecurityPlain(); #ifdef HAVE_GNUTLS case secTypeTLSNone: return new SSecurityStack(secTypeTLSNone, new SSecurityTLS(true)); case secTypeTLSVnc: return new SSecurityStack(secTypeTLSVnc, new SSecurityTLS(true), new SSecurityVncAuth()); + case secTypeTLSPlain: + return new SSecurityStack(secTypeTLSPlain, new SSecurityTLS(true), new SSecurityPlain()); case secTypeX509None: return new SSecurityStack(secTypeX509None, new SSecurityTLS(false)); case secTypeX509Vnc: return new SSecurityStack(secTypeX509None, new SSecurityTLS(false), new SSecurityVncAuth()); + case secTypeX509Plain: + return new SSecurityStack(secTypeX509Plain, new SSecurityTLS(false), new SSecurityPlain()); #endif } diff --git a/configure.ac b/configure.ac index 5acd7627..c411f8a7 100644 --- a/configure.ac +++ b/configure.ac @@ -82,6 +82,12 @@ fi AC_SUBST([GNUTLS_LIBS]) AM_CONDITIONAL([HAVE_GNUTLS], [ ! test "x$GNUTLS_LIBS" = x ]) +AC_CHECK_LIB([pam], [pam_start], + [PAM_LIBS='-lpam' + AC_DEFINE(HAVE_PAM, 1, [PAM available])]) +AC_SUBST([PAM_LIBS]) +AM_CONDITIONAL([HAVE_PAM], [ ! test "x$PAM_LIBS" = x ]) + VNCCONFIG_DIR='vncconfig' AC_ARG_ENABLE([vncconfig], AS_HELP_STRING([--enable-vncconfig], -- 2.39.5