commit 6610cd15cf186fe1f8e82628f6f12aa2c490bac2 Author: Timothy Pearson Date: Tue Mar 26 10:35:25 2013 -0500 Initial import of abandoned sc-ap project diff --git a/sc-ap/ldap1.cpp b/sc-ap/ldap1.cpp new file mode 100755 index 0000000..435c210 --- /dev/null +++ b/sc-ap/ldap1.cpp @@ -0,0 +1,157 @@ +/* + $Id: ldap1.cpp,v 1.1.1.1 2005/07/07 15:05:59 oflebbe Exp $ + + Copyright (C) 2003 Olaf Flebbe, Science and Computing AG + o.flebbe@science-computing.de + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ +#define WINDOWS_MEAN_AND_LEAN +#define UNICODE + +#include "ldap1.h" + +void +CLDAP::do_query( const mystring& filter, const wchar_t *attrs[]) { + if (fp) { + fprintf(fp, "do_query %S\n", filter.c_str()); + fflush(fp); + } + + // this is extremly ugly: Why can't the compile not cast a wchar_t * to a PWCHAR??? + ldap_search_s( lp, (const PWCHAR) context.c_str(), LDAP_SCOPE_SUBTREE, + (const PWCHAR) filter.c_str(), (PWCHAR *) attrs, 0, &msg); + if (fp) { + fprintf(fp, "after ldap_search\n"); + fflush(fp); + } + if (msg != NULL) { + msg = ldap_first_entry( lp, msg); + } +} +mystring +CLDAP::queryAttr( const mystring &filter, const mystring &attr, bool *exists) { + + const wchar_t *attrs[]= { attr.c_str(), NULL} ; //= { attr.c_str(), NULL }; + + do_query( filter, attrs); + if (exists != NULL) + *exists = true; + while ( msg != NULL) { + BerElement *berPtr; + wchar_t *attrPtr = ldap_first_attribute( lp, msg, &berPtr); + while (attrPtr != NULL) { + wchar_t **valList = ldap_get_values( lp, msg, attrPtr); + for (unsigned int i = 0; i < ldap_count_values( valList); i++) + return mystring( valList[i]); + attrPtr = ldap_next_attribute( lp, msg, berPtr); + } + } + if (exists != NULL) + *exists = false; + return mystring(L""); +} + +stringSet +CLDAP::queryListOfAttr( const mystring &filter, const mystring &attr) { + stringSet listOfVal; + const wchar_t *attrs[]= { attr.c_str(), NULL} ; //= { attr.c_str(), NULL }; + do_query( filter, attrs); + while ( msg != NULL) { + BerElement *berPtr; + wchar_t *attrPtr = ldap_first_attribute( lp, msg, &berPtr); + while (attrPtr != NULL) { + wchar_t **valList = ldap_get_values( lp, msg, attrPtr); + for (unsigned int i = 0; i < ldap_count_values( valList); i++) + listOfVal.insert( mystring( valList[i])); + attrPtr = ldap_next_attribute( lp, msg, berPtr); + } + msg = ldap_next_entry( lp, msg); + } + return listOfVal; +} + +stringMap +CLDAP::querySetOfAttrs( const mystring &filter, const stringSet &attr) { + stringMap mapOfVal; + + const wchar_t **attrs; + attrs = (const wchar_t **) malloc( sizeof( wchar_t *) * (attr.size()+1)); + for (unsigned int i = 0; i < attr.size()+1; i++) + attrs[i] = NULL; + + const wchar_t **pat = attrs; + + for (stringSet::const_iterator ptr = attr.begin(); ptr != attr.end(); ptr++) { + *pat++ = ptr->c_str(); + } + + + do_query( filter, attrs); + while ( msg != NULL) { + BerElement *berPtr; + wchar_t *attrPtr = ldap_first_attribute( lp, msg, &berPtr); + while (attrPtr != NULL) { + wchar_t **valList = ldap_get_values( lp, msg, attrPtr); + + mapOfVal[ mystring( attrPtr)] = mystring( valList[0]); + attrPtr = ldap_next_attribute( lp, msg, berPtr); + } + msg = ldap_next_entry( lp, msg); + } + return mapOfVal; +} + +CLDAP::CLDAP( const std::list& servers, FILE *fp, const mystring& binddn, const mystring& bindpasswd) { + this->fp = fp; + msg = NULL; + for ( std::list::const_iterator ptr = servers.begin(); ptr != servers.end(); ptr++) { + lp = ldap_init( (const PWCHAR) ptr->c_str(), LDAP_PORT); + ULONG version = LDAP_VERSION3; + if (!lp) { + fprintf( fp, "ldap_init error on server %S\n", ptr->c_str()); + continue; + } + + int ret = ldap_set_option( lp, LDAP_OPT_VERSION, &version); + if (ret != LDAP_SUCCESS) { + fprintf( fp, "ldap_set_option error %x on server %S\n", ret, ptr->c_str()); + ldap_unbind( lp); + continue; + } + + if (binddn == L"" || bindpasswd == L"") { + ret = ldap_simple_bind_s( lp, NULL, NULL); + if (LDAP_SUCCESS != ret) { + if (fp) + fprintf( fp, "anonymous ldap_simple_bind_s error %x on server %S\n", ret, ptr->c_str()); + ldap_unbind( lp); + lp = NULL; + } + } else { + ret = ldap_simple_bind_s( lp, (PWCHAR) binddn.c_str(), (PWCHAR) bindpasswd.c_str()); + if (LDAP_SUCCESS != ret) { + if (fp) + fprintf( fp, "ldap_simple_bind_s error %x on server %S, basedn %S, passwd %S\n", + ret, ptr->c_str(), binddn.c_str(), bindpasswd.c_str()); + ldap_unbind( lp); + lp = NULL; + } + } + return; + } +} + diff --git a/sc-ap/ldap1.h b/sc-ap/ldap1.h new file mode 100755 index 0000000..6f86b7c --- /dev/null +++ b/sc-ap/ldap1.h @@ -0,0 +1,54 @@ +/* + $Id: ldap1.h,v 1.1.1.1 2005/07/07 15:05:59 oflebbe Exp $ + + Copyright (C) 2003 Olaf Flebbe, Science and Computing AG + o.flebbe@science-computing.de + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ +#ifndef LDAP1_H +#define LDAP1_H + +#define UNICODE +#define WINDOWS_LEAN_AND_MEAN + +#include +#include +#include +#include "typedefs.h" + +class CLDAP { +private: + FILE *fp; + LDAP *lp; + mystring context; + LDAPMessage *msg; + +protected: + void do_query( const mystring& filter, const wchar_t *attrs[]); + mystring queryAttr( const mystring &filter, const mystring &attr, bool *exists = NULL); + stringSet queryListOfAttr( const mystring &filter, const mystring &attr); + stringMap querySetOfAttrs( const mystring &filter, const stringSet &attr); + +public: + CLDAP( const std::list& host, FILE *fp, const mystring& binddn, const mystring& bindpasswd); + void setContext( const mystring &context) { + this->context = context; + } + +}; + +#endif diff --git a/sc-ap/ldapuser.cpp b/sc-ap/ldapuser.cpp new file mode 100755 index 0000000..062efd3 --- /dev/null +++ b/sc-ap/ldapuser.cpp @@ -0,0 +1,51 @@ +#include "ldapuser.h" + +mystring LDAPUser::getGidByUserName( const mystring &userName) { + + mystring filter = L"(&(uid="; + filter.append( userName); + filter.append( L")(objectClass=posixAccount))"); + + return queryAttr( filter, L"gidNumber"); +} + + +mystring +LDAPUser::getGroupByGid( const mystring& gid) { + mystring filter = L"(&(gidNumber=" + gid + L")(objectClass=posixGroup))"; + mystring result = queryAttr( filter, L"cn"); + if (result == L"") { + return gid; + } + return result; +} + +stringSet +LDAPUser::getGroupsByUserName( const mystring& user, const mystring& gid) { + mystring filter = L"(&(|(gidNumber=" + gid + L")(memberUid=" + user + L"))(objectClass=posixGroup))"; + stringSet list1 = queryListOfAttr( filter, L"cn"); + + return list1; +} + +stringSet +LDAPUser::getUserNames() { + mystring filter = L"(objectClass=posixAccount)"; + return queryListOfAttr( filter, L"uid"); +} + +stringSet +LDAPUser::getGroupNames() { + mystring filter = L"(objectClass=posixGroup)"; + return queryListOfAttr( filter, L"cn"); +} + +stringMap +LDAPUser::getAttribsByUserName( const mystring &userName, const stringSet attribs) { + + mystring filter = L"(&(uid="; + filter.append( userName); + filter.append( L")(objectClass=posixAccount))"); + + return querySetOfAttrs( filter, attribs); +} diff --git a/sc-ap/ldapuser.h b/sc-ap/ldapuser.h new file mode 100755 index 0000000..0b1a096 --- /dev/null +++ b/sc-ap/ldapuser.h @@ -0,0 +1,14 @@ +#include "ldap1.h" + +class LDAPUser : public CLDAP { +public: + inline LDAPUser( const std::list& host, FILE *fp, const mystring& binddn, const mystring& bindpasswd) : + CLDAP( host, fp, binddn, bindpasswd) {}; + + mystring getGidByUserName( const mystring &str); + stringSet getGroupsByUserName( const mystring &str, const mystring &gid); + mystring getGroupByGid( const mystring &str); + stringMap getAttribsByUserName( const mystring &userName, const stringSet attribs); + stringSet getUserNames(); + stringSet getGroupNames(); +}; diff --git a/sc-ap/manageUser.cpp b/sc-ap/manageUser.cpp new file mode 100755 index 0000000..395bfae --- /dev/null +++ b/sc-ap/manageUser.cpp @@ -0,0 +1,159 @@ +/* + $Id: manageUser.cpp,v 1.1.1.1 2005/07/07 15:05:59 oflebbe Exp $ + + Copyright (C) 2003 Olaf Flebbe, Science and Computing AG + o.flebbe@science-computing.de + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ +#include +#include "ldapuser.h" +#include "netusergroup.h" +#include "utility.h" +#include "manageUser.h" +#include "reg.h" + +#define SCAPKEY L"Software\\science + computing\\scap" + + + + +void +manageLocalAccount( const mystring& userName, FILE *fp) { + + Registry reg( SCAPKEY); + // get LDAP Servers + std::list ldapservers = reg.getValues( L"servers"); + if (ldapservers.size() == 0) { + if (fp) + fprintf( fp, "ldapservers empty: Please set REG_MULTI_SZ value in HKLM\\%S\\servers", SCAPKEY); + return; + } + mystring binddn = reg.getValue( L"binddn"); + mystring bindpasswd = reg.getValue( L"bindpasswd"); + + // make bind + LDAPUser ld( ldapservers, fp, binddn, bindpasswd); + + mystring basedn = reg.getValue( L"basedn"); + if (basedn == L"") { + if (fp) + fprintf( fp, "basedn empty: Please set REG_SZ in HKLM\\%S\\basedn", SCAPKEY); + return; + } + ld.setContext( basedn); + + stringSet userAttrs; + +#define SAMBAHOMEPATH L"sambaHomePath" +#define HOMEDIRECTORY L"homeDirectory" +#define SAMBAHOMEDRIVE L"sambaHomeDrive" +#define SAMBAPROFILEPATH L"sambaProfilePath" +#define SAMBALOGONSCRIPT L"sambaLogonScript" + + userAttrs.insert( SAMBAHOMEPATH); + userAttrs.insert( HOMEDIRECTORY); + userAttrs.insert( SAMBAHOMEDRIVE); + userAttrs.insert( SAMBAPROFILEPATH ); + userAttrs.insert( SAMBALOGONSCRIPT); + userAttrs.insert( L"gidNumber"); + + stringMap userVals = ld.getAttribsByUserName( userName, userAttrs); + + if (userVals.size() == 0 || (userVals.find( L"gidNumber") == userVals.end())) { + // nothing found + if (fp) { + fprintf( fp, "user %S not found in LDAP: trying to delete user account\n", userName.c_str()); + fflush( fp); + } + fprintf( fp, "isdisabled %d\n", isDisabledUser( userName)); + // if local user exists and is disabled: delete! + if (isDisabledUser( userName) == 1) + delUser( userName); + return; + } + if (fp) { + fprintf( fp, "add user %S\n", userName.c_str()); + fflush( fp); + } + mystring gid = userVals[ L"gid"]; + + // homepath + mystring homePath; + if (userVals.find( SAMBAHOMEPATH) != userVals.end()) { + homePath = userVals[ SAMBAHOMEPATH]; // use first Element + } else { + if (userVals.find( HOMEDIRECTORY) != userVals.end()) { + homePath = userVals[ HOMEDIRECTORY]; + } else { + homePath = reg.getValue( L"homepath"); + } + // search and replace with registry keys + homePath = searchAndReplace( convertSlashes( homePath), L"homepathreplace", reg, fp); + } + + // homedrive + mystring homeDrive; + if (userVals.find( SAMBAHOMEDRIVE) != userVals.end()) { + homeDrive = *(userVals[ SAMBAHOMEDRIVE].begin()); // use first Element + } else { + homeDrive = reg.getValue( L"homedrive"); + } + + // profilePath + mystring profilePath; + if (userVals.find( SAMBAPROFILEPATH) != userVals.end()) { + profilePath = userVals[ SAMBAPROFILEPATH]; + } else { + if (homeDrive != L"") { + profilePath= homeDrive + reg.getValue( L"profilepath"); + } else { + profilePath = homePath + reg.getValue( L"profilepath"); + profilePath = searchAndReplace( profilePath, L"profilereplace", reg, fp); + } + } + //logonscript + mystring logonScript; + if (userVals.find( SAMBALOGONSCRIPT) != userVals.end()) { + logonScript = userVals[ SAMBALOGONSCRIPT]; + } else { + logonScript = reg.getValue( L"logonscript"); + } + + + + // add user only if it does not exists before. + // Do not clutter Event Log + if (-1 == isDisabledUser( userName)) + addUser( userName, homePath, homeDrive, profilePath, logonScript ); + stringSet ldapList = ld.getGroupsByUserName( userName, gid); + stringSet ntList = listGroups( userName); + stringSet worker; + std::set_difference( ldapList.begin(), ldapList.end(), ntList.begin(), ntList.end(), std::inserter(worker, worker.begin())); + // worker is now Groups containe not in ntlist but ldapList -> add to user + + for (stringSet::const_iterator ptr = worker.begin(); ptr != worker.end(); ptr++) { + fprintf( fp, "add to group %S\n", ptr->c_str()); + addUserToGroup( userName, *ptr); + } + std::set_difference( ntList.begin(), ntList.end(), ldapList.begin(), ldapList.end(), std::inserter(worker, worker.begin())); + // worker is now Groups containe not in ntlist but ldapList -> add to user + for (stringSet::const_iterator ptr = worker.begin(); ptr != worker.end(); ptr++) { + fprintf( fp, "remove from group %S\n", ptr->c_str()); + delUserFromGroup( userName, *ptr); + } + fflush( fp); +} diff --git a/sc-ap/manageUser.h b/sc-ap/manageUser.h new file mode 100755 index 0000000..9218439 --- /dev/null +++ b/sc-ap/manageUser.h @@ -0,0 +1,33 @@ +/* + $Id: manageUser.h,v 1.1.1.1 2005/07/07 15:05:59 oflebbe Exp $ + + Copyright (C) 2003 Olaf Flebbe, Science and Computing AG + o.flebbe@science-computing.de + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ +#ifndef MANAGE_USER_H +#define MANAGE_USER_H + +#define WINDOWS_MEAN_AND_LEAN +#define UNICODE + +#include +#include "typedefs.h" +void +manageLocalAccount( const mystring& userName, FILE *fp); + +#endif diff --git a/sc-ap/netusergroup.cpp b/sc-ap/netusergroup.cpp new file mode 100755 index 0000000..a8e34c0 --- /dev/null +++ b/sc-ap/netusergroup.cpp @@ -0,0 +1,260 @@ +/* + $Id: netusergroup.cpp,v 1.1.1.1 2005/07/07 15:05:59 oflebbe Exp $ + + Copyright (C) 2003 Olaf Flebbe, Science and Computing AG + o.flebbe@science-computing.de + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ +#define WINDOWS_MEAN_AND_LEAN +#define UNICODE + +#include +#include +#include "netusergroup.h" + +int +addUserToGroup( const mystring& userName, const mystring& groupName) { + if (addGroup( groupName)) { + return 1; + } + + LOCALGROUP_MEMBERS_INFO_3 gmember; + gmember.lgrmi3_domainandname = (LPWSTR) userName.c_str(); + int ret = NetLocalGroupAddMembers( NULL, groupName.c_str(), 3, (LPBYTE )&gmember, 1); + if (!(ret == NERR_Success || ret == ERROR_MEMBER_IN_ALIAS)) + return 1; + return 0; +} + +int +delUserFromGroup( const mystring& userName, const mystring& groupName) { + LOCALGROUP_MEMBERS_INFO_3 gmember; + gmember.lgrmi3_domainandname = (LPWSTR) userName.c_str(); + int ret = NetLocalGroupDelMembers( NULL, groupName.c_str(), 3, (LPBYTE )&gmember, 1); + if (!(ret == NERR_Success || ret == ERROR_MEMBER_IN_ALIAS)) + return 1; + return 0; +} + + +int addGroup( const mystring& groupName) { +LOCALGROUP_INFO_0 gent; + gent.lgrpi0_name = wcsdup( groupName.c_str()); + int ret = NetLocalGroupAdd( NULL, 0, (LPBYTE )&gent, NULL); + free( gent.lgrpi0_name); + if (!(ret == NERR_Success || ret == NERR_GroupExists || ret == ERROR_ALIAS_EXISTS)) { + return 1; + } + return 0; +} + +int +addUser( const mystring& userName) { + USER_INFO_1 ui; + + ui.usri1_name = (LPWSTR) userName.c_str(); + ui.usri1_password = L"xyzzy"; + ui.usri1_flags = UF_SCRIPT | UF_PASSWD_CANT_CHANGE | UF_ACCOUNTDISABLE; + + ui.usri1_script_path = NULL; + ui.usri1_priv = USER_PRIV_USER; + ui.usri1_comment = NULL; + ui.usri1_home_dir = NULL; + ui.usri1_password_age = 0; + + int ret = NetUserAdd( NULL,1, (LPBYTE )&ui, NULL); + return (!(ret == NERR_Success || ret == NERR_UserExists)); +} + +int addUser( const mystring& userName, const mystring& homepath, const mystring& homedrive, + const mystring& profile, const mystring& script) { + USER_INFO_4 ui; /* INFO_3 für 2000? */ + + memset( &ui, 0, sizeof( ui)); + ui.usri4_name = (LPWSTR) userName.c_str(); + ui.usri4_password = L"xyzzy"; + ui.usri4_priv = USER_PRIV_USER; + ui.usri4_home_dir = (LPWSTR) homepath.c_str(); + + ui.usri4_flags = UF_SCRIPT | UF_PASSWD_CANT_CHANGE | UF_ACCOUNTDISABLE; + + ui.usri4_script_path = (LPWSTR) script.c_str(); + ui.usri4_max_storage = USER_MAXSTORAGE_UNLIMITED; + ui.usri4_country_code = 0; /* Arghhh! not documented*/ + ui.usri4_code_page = 1252; + + ui.usri4_primary_group_id = DOMAIN_GROUP_RID_USERS; + + ui.usri4_profile = (LPWSTR) profile.c_str(); + ui.usri4_home_dir_drive = (LPWSTR) homedrive.c_str(); + int ret = NetUserAdd( NULL, 4, (LPBYTE )&ui, NULL); + return (!(ret == NERR_Success || ret == NERR_UserExists)); +} +// return 1: User exists and disabled +// return 0: User exists and enabled +// return -1: User does not exist +int +isDisabledUser( const mystring& userName) { + + // This API is sick + LPUSER_INFO_1 ui = NULL; + int flag = -1; + if (NERR_Success == NetUserGetInfo( NULL, userName.c_str(), 1, (LPBYTE *)&ui)) { + flag = (ui->usri1_flags & UF_ACCOUNTDISABLE) == UF_ACCOUNTDISABLE; + } + if (ui != NULL) + NetApiBufferFree( ui); + return flag; +} + +int +delUser( const mystring& userName) { + return NetUserDel( NULL, userName.c_str()); +} + +stringSet +listGroups( const mystring& user) { + LPLOCALGROUP_USERS_INFO_0 pBuf = NULL; + LPLOCALGROUP_USERS_INFO_0 pTmpBuf; + + DWORD dwPrefMaxLen = MAX_PREFERRED_LENGTH; + DWORD dwEntriesRead = 0; + DWORD dwTotalEntries = 0; + + DWORD i; + DWORD dwTotalCount = 0; + NET_API_STATUS nStatus; + stringSet groupList; + + do + { + if (pBuf != NULL) { + NetApiBufferFree(pBuf); + pBuf = NULL; + } + nStatus = NetUserGetLocalGroups( NULL, + user.c_str(), + 0, + 0, + (LPBYTE*)&pBuf, + dwPrefMaxLen, + &dwEntriesRead, + &dwTotalEntries); + dwPrefMaxLen = dwTotalEntries; + // TODO: Endless loop possible? + } while (nStatus == ERROR_MORE_DATA); + // + // If the call succeeds, + // + if (nStatus == NERR_Success) { + if ((pTmpBuf = pBuf) != NULL) { + // + // Loop through the entries. + // + for (i = 0; (i < dwEntriesRead); i++) { + groupList.insert( mystring( pTmpBuf->lgrui0_name)); + pTmpBuf++; + } + } + else + return groupList; + } + // + // Free the allocated buffer. + // + if (pBuf != NULL) + { + NetApiBufferFree(pBuf); + pBuf = NULL; + } + + return groupList; +} + + +stringSet +listUsers() { + LPUSER_INFO_0 pBuf = NULL; + LPUSER_INFO_0 pTmpBuf; + DWORD dwPrefMaxLen = MAX_PREFERRED_LENGTH; + DWORD dwEntriesRead = 0; + DWORD dwTotalEntries = 0; + DWORD dwResumeHandle = 0; + DWORD i; + DWORD dwTotalCount = 0; + NET_API_STATUS nStatus; + stringSet userList; + // + // Call the NetUserEnum function, specifying level 0; + // enumerate global user account types only. + // + do // begin do + { + if (pBuf != NULL) { + NetApiBufferFree(pBuf); + pBuf = NULL; + } + nStatus = NetUserEnum( NULL, + 0, + FILTER_NORMAL_ACCOUNT, // global users + (LPBYTE*)&pBuf, + dwPrefMaxLen, + &dwEntriesRead, + &dwTotalEntries, + &dwResumeHandle); + // + // If the call succeeds, + // + if ((nStatus == NERR_Success) || (nStatus == ERROR_MORE_DATA)) + { + if ((pTmpBuf = pBuf) != NULL) + { + // + // Loop through the entries. + // + for (i = 0; (i < dwEntriesRead); i++) + { + userList.insert( mystring( pTmpBuf->usri0_name)); + pTmpBuf++; + dwTotalCount++; + } + } + } + + else + return userList; + // + // Free the allocated buffer. + // + if (pBuf != NULL) + { + NetApiBufferFree(pBuf); + pBuf = NULL; + } + } + // Continue to call NetUserEnum while + // there are more entries. + // + while (nStatus == ERROR_MORE_DATA); // end do + // + // Check again for allocated memory. + // + if (pBuf != NULL) + NetApiBufferFree(pBuf); + + return userList; +} \ No newline at end of file diff --git a/sc-ap/netusergroup.h b/sc-ap/netusergroup.h new file mode 100755 index 0000000..6bf8179 --- /dev/null +++ b/sc-ap/netusergroup.h @@ -0,0 +1,56 @@ +/* + $Id: netusergroup.h,v 1.1.1.1 2005/07/07 15:05:59 oflebbe Exp $ + + Copyright (C) 2003 Olaf Flebbe, Science and Computing AG + o.flebbe@science-computing.de + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ +#ifndef NETUSERGROUP_H +#define NETUSERGROUP_H +#define WINDOWS_MEAN_AND_LEAN +#define UNICODE + +#include +#include "typedefs.h" + +int +addUserToGroup( const mystring& userName, const mystring& groupName); + +int +delUserFromGroup( const mystring& userName, const mystring& groupName); + +int +addUser( const mystring& userName); +int +addUser( const mystring& userName, const mystring& homepath, const mystring& homedrive, + const mystring& profile, const mystring& script); + +int +addGroup( const mystring& userName); + +int +delUser( const mystring& userName); + +int +isDisabledUser( const mystring& userName); + +stringSet +listUsers(); + +stringSet +listGroups( const mystring& user); +#endif diff --git a/sc-ap/reg.cpp b/sc-ap/reg.cpp new file mode 100755 index 0000000..03946ac --- /dev/null +++ b/sc-ap/reg.cpp @@ -0,0 +1,144 @@ +/* + $Id: reg.cpp,v 1.1.1.1 2005/07/07 15:05:59 oflebbe Exp $ + + Copyright (C) 2003 Olaf Flebbe, Science and Computing AG + o.flebbe@science-computing.de + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include "reg.h" + + +Registry::Registry( const mystring key) { + keyHandle = 0; + if (ERROR_SUCCESS != RegOpenKeyEx( HKEY_LOCAL_MACHINE, key.c_str(), 0, KEY_QUERY_VALUE|KEY_ENUMERATE_SUB_KEYS , &keyHandle)) + return; +} + +Registry::~Registry() { + if (keyHandle != NULL) + RegCloseKey( keyHandle); +} + +mystring Registry::getValue( const mystring& value) const { + wchar_t *retBuf = NULL; + DWORD retBufSize = 128; + + while (1) { + retBuf = new wchar_t[ retBufSize]; //o.k. not clean alloc twice as needed + DWORD type; + long ret = RegQueryValueEx( keyHandle, value.c_str(), 0, &type, (LPBYTE) retBuf, &retBufSize); + if (ret == ERROR_MORE_DATA) { + delete[] retBuf; + continue; + } + if (ret != ERROR_SUCCESS || type != REG_SZ) + return mystring(L""); + break; + } + mystring ret( retBuf); + delete[] retBuf; + return ret; +} + +std::list Registry::getValues( const mystring& value) const { + wchar_t *retBuf = NULL; + DWORD retBufSize = 128; + std::list list; + while (1) { + retBuf = new wchar_t[ retBufSize]; //o.k. not clean alloc twice as needed + DWORD type; + long ret = RegQueryValueEx( keyHandle, value.c_str(), 0, &type, (LPBYTE) retBuf, &retBufSize); + if (ret == ERROR_MORE_DATA) { + delete[] retBuf; + continue; + } + if (ret != ERROR_SUCCESS || type != REG_MULTI_SZ) { + delete[] retBuf; + return list; + } + break; + } + + wchar_t *ptr = retBuf; + while (*ptr != 0) { + list.push_back( mystring( ptr)); + while (*ptr != 0) + ptr++; + // ptr points to terminating 0 + ptr++; + // should point to new entry, or terminating 0 + } + delete[] retBuf; + return list; +} + +std::list Registry::getSubKeys() const { + wchar_t *retBuf = NULL; + DWORD retBufSize = 128; + std::list list; + int numKey =0; + long ret; + do { + + while (1) { + retBuf = new wchar_t[ retBufSize]; //o.k. not clean alloc twice as needed + FILETIME mod; + ret = RegEnumKeyEx( keyHandle, numKey, retBuf, &retBufSize, 0, NULL, NULL, &mod); + if (ret == ERROR_MORE_DATA) { + delete[] retBuf; + retBufSize *= 2; + continue; + } + if (!(ret == ERROR_NO_MORE_ITEMS || ret== ERROR_SUCCESS)){ + delete[] retBuf; + return list; + } + break; + } + if (ret == ERROR_SUCCESS) { + list.push_back( mystring(retBuf)); + } + delete[] retBuf; + numKey++; + } while (ret != ERROR_NO_MORE_ITEMS); + return list; +} + +bool Registry::exists( const mystring& value) { + if (keyHandle) { + int ret = RegQueryValueEx( keyHandle, value.c_str(), 0, NULL, NULL, NULL); + return (ret == ERROR_SUCCESS); + } + return false; +} + +#if 0 +main() { + Registry reg( L"SOFTWARE\\science + computing\\scap"); + printf("%S\n", reg.getValue( L"basedn").c_str()); + std::list servers = reg.getValues( L"servers"); + for (std::list::const_iterator ptr = servers.begin(); ptr != servers.end(); ptr++) { + printf("%S\n", ptr->c_str()); + } + Registry zwo( L"System\\CurrentControlSet\\Control\\Lsa\\Kerberos\\Domains"); + std::list realms = zwo.getSubKeys(); + for (std::list::const_iterator ptr = realms.begin(); ptr != realms.end(); ptr++) { + printf("%S\n", ptr->c_str()); + } +} +#endif diff --git a/sc-ap/reg.h b/sc-ap/reg.h new file mode 100755 index 0000000..25e375e --- /dev/null +++ b/sc-ap/reg.h @@ -0,0 +1,44 @@ +/* + $Id: reg.h,v 1.1.1.1 2005/07/07 15:05:59 oflebbe Exp $ + + Copyright (C) 2003 Olaf Flebbe, Science and Computing AG + o.flebbe@science-computing.de + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ +#ifndef REG_H +#define REG_H + +#define UNICODE +#define WINDOWS_LEAN_AND_MEAN + +#include +#include "typedefs.h" + +class Registry { + HKEY keyHandle; +public: + Registry( const mystring key); + mystring getValue( const mystring& value) const; + std::list getValues( const mystring& value) const; + ~Registry(); + std::list getSubKeys() const; + inline bool exists() const { + return keyHandle != NULL; + } + bool exists( const mystring& value); +}; +#endif diff --git a/sc-ap/sspap3.cpp b/sc-ap/sspap3.cpp new file mode 100755 index 0000000..d95c124 --- /dev/null +++ b/sc-ap/sspap3.cpp @@ -0,0 +1,249 @@ +/* + $Id: sspap3.cpp,v 1.1.1.1 2005/07/07 15:05:59 oflebbe Exp $ + + Copyright (C) 2003 Olaf Flebbe, Science and Computing AG + o.flebbe@science-computing.de + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ +#define UNICODE +#define SECURITY_WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#include +#include +#include +#include +//#include +#include +//#include +#include +#include +#include +#include "reg.h" + +HMODULE msvHandle = 0; +#include "manageUser.h" + +extern "C" { + + NTSTATUS SEC_ENTRY SpUserModeInitialize( + ULONG LsaVersion, + PULONG PackageVersion, + PSECPKG_USER_FUNCTION_TABLE* ppTables, + PULONG pcTables + ) { + if (!msvHandle) + msvHandle = LoadLibrary(L"kerberos.dll"); + + NTSTATUS status = (*((SpUserModeInitializeFn ) GetProcAddress( msvHandle, "SpUserModeInitialize"))) + (LsaVersion, PackageVersion,ppTables, pcTables ); + return status; + } + + SpInitializeFn *oldSpInitialize = 0; + + // SpInitialize is special, it should be both exported + // and be referenced in the SpLsaModeInitialize Call + NTSTATUS SEC_ENTRY SpInitialize( + ULONG_PTR PackageId, + PSECPKG_PARAMETERS Parameters, + PLSA_SECPKG_FUNCTION_TABLE FunctionTable) { + + if (oldSpInitialize == 0) { + if (!msvHandle) + msvHandle = LoadLibrary(L"kerberos.dll"); + + + NTSTATUS status = (*((SpInitializeFn *) GetProcAddress( msvHandle, "SpInitialize"))) + (PackageId, Parameters,FunctionTable ); + + return status; + } else { + return (*oldSpInitialize)( PackageId, Parameters,FunctionTable); + } + } + + // Todo: Should be wrapped too + + NTSTATUS SEC_ENTRY SpInstanceInit( + ULONG Version, + PSECPKG_DLL_FUNCTIONS FunctionTable, + PVOID* UserFunctions + ) { + if (!msvHandle) + msvHandle = LoadLibrary(L"kerberos.dll"); + + NTSTATUS status = (*((SpInstanceInitFn *) GetProcAddress( msvHandle, "SpInstanceInit"))) + (Version, FunctionTable, UserFunctions); + + return status; + } + + + PLSA_AP_LOGON_USER_EX2 oldLogonUserEx2 = 0; + + + NTSTATUS NTAPI + myLogonUserEx2( + PLSA_CLIENT_REQUEST ClientRequest, + SECURITY_LOGON_TYPE LogonType, + PVOID AuthenticationInformation, + PVOID ClientAuthenticationBase, + ULONG AuthenticationInformationLength, + PVOID* ProfileBuffer, + PULONG ProfileBufferLength, + PLUID LogonId, + PNTSTATUS SubStatus, + PLSA_TOKEN_INFORMATION_TYPE TokenInformationType, + PVOID* TokenInformation, + PUNICODE_STRING* AccountName, + PUNICODE_STRING* AuthenticatingAuthority, + PUNICODE_STRING* MachineName, + PSECPKG_PRIMARY_CRED PrimaryCredentials, + PSECPKG_SUPPLEMENTAL_CRED_ARRAY* SupplementalCredentials + ) { + FILE *fp = fopen("C:\\lsa.txt", "ab"); + fprintf( fp, "LogonUserEx2 %d\n", LogonType); //,ClientAuthenticationBase, AuthenticationInformationLength, ClientRequest ); + for (unsigned int i = 0; i < AuthenticationInformationLength; i++) { + fprintf( fp, "%02x ", (char) ((char *) AuthenticationInformation)[i]); + } + fprintf( fp, "\n----\n"); + // fwrite( AuthenticationInformation, AuthenticationInformationLength, 1, fp); + fflush(fp); + KERB_INTERACTIVE_LOGON *ptr = ((KERB_INTERACTIVE_LOGON *)AuthenticationInformation); + if (LogonType == 2 && ptr->MessageType == KerbInteractiveLogon) { + LPWSTR userName = (LPWSTR) calloc( ptr->UserName.Length + 2, 1); + LPWSTR domain = (LPWSTR) calloc( ptr->LogonDomainName.Length + 2, 1); + if (userName && domain) { + wcsncpy( userName, (wchar_t *) ((char *) ptr + ((char *)ptr->UserName.Buffer - (char *) ClientAuthenticationBase)), ptr->UserName.Length / 2); + wcsncpy( domain, (wchar_t *) ((char *) ptr + ((char *)ptr->LogonDomainName.Buffer - (char *) ClientAuthenticationBase)), ptr->LogonDomainName.Length / 2); + + Registry kerbReg( L"System\\CurrentControlSet\\Control\\Lsa\\Kerberos\\Domains"); + std::list realms = kerbReg.getSubKeys(); + + mystring strDomain( domain); + // if logon domain is a kerberos realm, create and delete users and groups according to LDAP entries + if ( std::find( realms.begin(), realms.end(), mystring( domain)) != realms.end()) + + manageLocalAccount( userName, fp); + } + if (userName) + free( userName); + if (domain) + free( domain); + } + fflush(fp); + NTSTATUS status = (*oldLogonUserEx2) + (ClientRequest, LogonType, AuthenticationInformation, ClientAuthenticationBase, + AuthenticationInformationLength, ProfileBuffer, ProfileBufferLength, + LogonId, SubStatus, TokenInformationType, TokenInformation, + AccountName, AuthenticatingAuthority, MachineName, PrimaryCredentials, + SupplementalCredentials); + + + fprintf( fp, "LogonUserEx2 %x Fertig\n", status); + fclose( fp); + return status; + } + + PLSA_AP_CALL_PACKAGE oldCallPackage = 0; + + NTSTATUS + myCallPackage( + PLSA_CLIENT_REQUEST ClientRequest, + PVOID ProtocolSubmitBuffer, + PVOID ClientBufferBase, + ULONG SubmitBufferLength, + PVOID* ProtocolReturnBuffer, + PULONG ReturnBufferLength, + PNTSTATUS ProtocolStatus + ) { + FILE *fp = fopen("C:\\lsa.txt", "a"); + fprintf( fp, "LsaApCallPackage\n"); + fclose( fp); + NTSTATUS status = (*oldCallPackage) + (ClientRequest, ProtocolSubmitBuffer, ClientBufferBase, SubmitBufferLength, + ProtocolReturnBuffer, ReturnBufferLength, ProtocolStatus); + return status; + } + + PLSA_AP_CALL_PACKAGE_PASSTHROUGH oldCallPackagePassthrough = 0; + + NTSTATUS myCallPackagePassthrough( + PLSA_CLIENT_REQUEST ClientRequest, + PVOID ProtocolSubmitBuffer, + PVOID ClientBufferBase, + ULONG SubmitBufferLength, + PVOID* ProtocolReturnBuffer, + PULONG ReturnBufferLength, + PNTSTATUS ProtocolStatus + ) + { + FILE *fp = fopen("C:\\lsa.txt", "a"); + fprintf( fp, "LsaApCallPackagePassThrough\n"); + fclose( fp); + return (*oldCallPackagePassthrough) + (ClientRequest, ProtocolSubmitBuffer, ClientBufferBase, SubmitBufferLength, + ProtocolReturnBuffer, ReturnBufferLength, ProtocolStatus); + } + + PLSA_AP_CALL_PACKAGE_PASSTHROUGH oldCallPackageUntrusted = 0; + + NTSTATUS myCallPackageUntrusted( + PLSA_CLIENT_REQUEST ClientRequest, + PVOID ProtocolSubmitBuffer, + PVOID ClientBufferBase, + ULONG SubmitBufferLength, + PVOID* ProtocolReturnBuffer, + PULONG ReturnBufferLength, + PNTSTATUS ProtocolStatus + ) { + FILE *fp = fopen("C:\\lsa.txt", "a"); + fprintf( fp, "LsaApCallPackagePassUntrusted\n"); + fclose( fp); + return (*oldCallPackageUntrusted) + (ClientRequest, ProtocolSubmitBuffer, ClientBufferBase, SubmitBufferLength, + ProtocolReturnBuffer, ReturnBufferLength, ProtocolStatus); + } + + + NTSTATUS NTAPI SpLsaModeInitialize( + ULONG LsaVersion, + PULONG PackageVersion, + PSECPKG_FUNCTION_TABLE* ppTables, + PULONG pcTables + ) { + if (!msvHandle) + msvHandle = LoadLibrary(L"kerberos.dll"); + + + NTSTATUS status = (*((SpLsaModeInitializeFn ) GetProcAddress( msvHandle, "SpLsaModeInitialize"))) + (LsaVersion, PackageVersion, ppTables, pcTables); + oldLogonUserEx2 = (*ppTables)->LogonUserEx2; + (*ppTables)->LogonUserEx2 = &myLogonUserEx2; + oldCallPackage = (*ppTables)->CallPackage; + (*ppTables)->CallPackage = &myCallPackage; + oldCallPackagePassthrough = (*ppTables)->CallPackagePassthrough; + (*ppTables)->CallPackagePassthrough = &myCallPackagePassthrough; + oldCallPackageUntrusted = (*ppTables)->CallPackageUntrusted; + (*ppTables)->CallPackageUntrusted = &myCallPackageUntrusted; + + oldSpInitialize = (*ppTables)->Initialize; + (*ppTables)->Initialize = &SpInitialize; + return status; + } +} diff --git a/sc-ap/sspap3.def b/sc-ap/sspap3.def new file mode 100755 index 0000000..0ab8d89 --- /dev/null +++ b/sc-ap/sspap3.def @@ -0,0 +1,9 @@ +LIBRARY sspap3 + +EXPORTS + SpUserModeInitialize + SpInitialize + SpInstanceInit + SpLsaModeInitialize + + \ No newline at end of file diff --git a/sc-ap/sspap3.sln b/sc-ap/sspap3.sln new file mode 100755 index 0000000..7f6cf19 --- /dev/null +++ b/sc-ap/sspap3.sln @@ -0,0 +1,21 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sspap3", "sspap3.vcproj", "{EA164A0F-6361-40D6-B356-B6E16EB9FA15}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + Debug = Debug + Release = Release + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {EA164A0F-6361-40D6-B356-B6E16EB9FA15}.Debug.ActiveCfg = Debug|Win32 + {EA164A0F-6361-40D6-B356-B6E16EB9FA15}.Debug.Build.0 = Debug|Win32 + {EA164A0F-6361-40D6-B356-B6E16EB9FA15}.Release.ActiveCfg = Release|Win32 + {EA164A0F-6361-40D6-B356-B6E16EB9FA15}.Release.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/sc-ap/sspap3.vcproj b/sc-ap/sspap3.vcproj new file mode 100755 index 0000000..6ed8c9c --- /dev/null +++ b/sc-ap/sspap3.vcproj @@ -0,0 +1,182 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sc-ap/typedefs.h b/sc-ap/typedefs.h new file mode 100755 index 0000000..ac3aedc --- /dev/null +++ b/sc-ap/typedefs.h @@ -0,0 +1,14 @@ +#ifndef TYPEDEFS_H +#define TYPEDEFS_H + +#include +#include +#include +#include + +typedef std::wstring mystring; +typedef std::set stringSet; +typedef std::map stringMap; +typedef std::list stringList; +#endif + diff --git a/sc-ap/utility.cpp b/sc-ap/utility.cpp new file mode 100755 index 0000000..dd78a4c --- /dev/null +++ b/sc-ap/utility.cpp @@ -0,0 +1,68 @@ +/* + $Id: utility.cpp,v 1.1.1.1 2005/07/07 15:05:59 oflebbe Exp $ + + Copyright (C) 2003 Olaf Flebbe, Science and Computing AG + o.flebbe@science-computing.de + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ +#include +#include + +#include "utility.h" + +mystring itos( int a) { + std::wstringstream ostr; + + ostr << a; + return ostr.str(); +} + +mystring convertSlashes( const mystring& input) { + mystring tmpInput = input; + // replace / by \ - + std::replace( tmpInput.begin(), tmpInput.end(), L'/', L'\\'); + // collapse \\ to \ -- + mystring::size_type a; + + while ((a = tmpInput.find( L"\\\\")) != mystring::npos) { + tmpInput.replace( a, 2, L"\\"); + } + return tmpInput; +} + +mystring searchAndReplace( const mystring& inputString, const mystring& registryKey, Registry ®, FILE *fp) { + mystring tmpInputString = inputString; + int i = 0; + while (reg.exists( registryKey + itos( i))) { + stringList searchReplace = reg.getValues( registryKey + itos( i)); + if (searchReplace.size() != 2) { + fprintf( fp, "registry key prependpath %d invalid\n", i); + continue; + } + mystring searchString = searchReplace.front(); + searchReplace.pop_front(); + mystring replaceString = searchReplace.front(); + if (tmpInputString.size() < searchString.size()) + continue; + // check whether search matches + if (std::equal( searchString.begin(), searchString.end(), tmpInputString.begin())) { + tmpInputString.replace( 0, searchString.size(), replaceString); + } + i++; + } + return tmpInputString; +} diff --git a/sc-ap/utility.h b/sc-ap/utility.h new file mode 100755 index 0000000..3ea1f01 --- /dev/null +++ b/sc-ap/utility.h @@ -0,0 +1,34 @@ +/* + $Id: utility.h,v 1.1.1.1 2005/07/07 15:05:59 oflebbe Exp $ + + Copyright (C) 2003 Olaf Flebbe, Science and Computing AG + o.flebbe@science-computing.de + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#ifndef UTILITY_H +#define UTILITY_H + +#include +#include "typedefs.h" +#include "reg.h" + +mystring itos( int a); +mystring convertSlashes( const mystring& input); +mystring searchAndReplace( const mystring& inputString, const mystring& registryKey, Registry ®, FILE *fp); + +#endif \ No newline at end of file