syncserv.cpp 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. // Created: 2-8-2005
  2. // Author(s): Scott Bridges
  3. #include "syncserv.h"
  4. #include "prerror.h"
  5. static char* certdbh;
  6. char* passwdcb(PK11SlotInfo* info, PRBool retry, void* arg)
  7. {
  8. char* result = NULL;
  9. unsigned long resultLen = 0;
  10. DWORD type;
  11. HKEY regKey;
  12. if (!retry)
  13. {
  14. RegOpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\PasswordSync", &regKey);
  15. RegQueryValueEx(regKey, "Install Path", NULL, &type, NULL, &resultLen);
  16. result = (char*)malloc(resultLen);
  17. RegQueryValueEx(regKey, "Cert Token", NULL, &type, (unsigned char*)result, &resultLen);
  18. RegCloseKey(regKey);
  19. }
  20. return result;
  21. }
  22. PassSyncService::PassSyncService(const TCHAR *serviceName) : CNTService(serviceName)
  23. {
  24. char sysPath[SYNCSERV_BUF_SIZE];
  25. HKEY regKey;
  26. DWORD type;
  27. unsigned long size;
  28. passhookEventHandle = CreateEvent(NULL, FALSE, FALSE, PASSHAND_EVENT_NAME);
  29. pLdapConnection = NULL;
  30. results = NULL;
  31. currentResult = NULL;
  32. lastLdapError = LDAP_SUCCESS;
  33. certdbh = NULL;
  34. multipleModify = SYNCSERV_ALLOW_MULTI_MOD;
  35. isRunning = false;
  36. RegOpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\PasswordSync", &regKey);
  37. size = SYNCSERV_BUF_SIZE;
  38. RegQueryValueEx(regKey, "Install Path", NULL, &type, (unsigned char*)installPath, &size);
  39. size = SYNCSERV_BUF_SIZE;
  40. RegQueryValueEx(regKey, "Host Name", NULL, &type, (unsigned char*)ldapHostName, &size);
  41. size = SYNCSERV_BUF_SIZE;
  42. RegQueryValueEx(regKey, "Port Number", NULL, &type, (unsigned char*)ldapHostPort, &size);
  43. size = SYNCSERV_BUF_SIZE;
  44. RegQueryValueEx(regKey, "User Name", NULL, &type, (unsigned char*)ldapAuthUsername, &size);
  45. size = SYNCSERV_BUF_SIZE;
  46. RegQueryValueEx(regKey, "Password", NULL, &type, (unsigned char*)ldapAuthPassword, &size);
  47. size = SYNCSERV_BUF_SIZE;
  48. RegQueryValueEx(regKey, "Search Base", NULL, &type, (unsigned char*)ldapSearchBase, &size);
  49. size = SYNCSERV_BUF_SIZE;
  50. RegQueryValueEx(regKey, "User Name Field", NULL, &type, (unsigned char*)ldapUsernameField, &size);
  51. size = SYNCSERV_BUF_SIZE;
  52. RegQueryValueEx(regKey, "Password Field", NULL, &type, (unsigned char*)ldapPasswordField, &size);
  53. RegCloseKey(regKey);
  54. ExpandEnvironmentStrings("%SystemRoot%", sysPath, SYNCSERV_BUF_SIZE);
  55. _snprintf(certPath, SYNCSERV_BUF_SIZE, "%s", installPath);
  56. _snprintf(logPath, SYNCSERV_BUF_SIZE, "%spasssync.log", installPath);
  57. _snprintf(dataFilename, SYNCSERV_BUF_SIZE, "%s\\system32\\passhook.dat", sysPath);
  58. outLog.open(logPath, ios::out | ios::app);
  59. if(outLog.is_open())
  60. {
  61. timeStamp(&outLog);
  62. outLog << "begin log" << endl;
  63. }
  64. PK11_SetPasswordFunc(passwdcb);
  65. }
  66. PassSyncService::~PassSyncService()
  67. {
  68. if(outLog.is_open())
  69. {
  70. timeStamp(&outLog);
  71. outLog << "end log" << endl;
  72. }
  73. outLog.close();
  74. }
  75. int PassSyncService::SyncPasswords()
  76. {
  77. int result = 0;
  78. char username[PASSHAND_BUF_SIZE];
  79. char password[PASSHAND_BUF_SIZE];
  80. char* dn;
  81. if(Connect() < 0)
  82. {
  83. // ToDo: generate event connection failure.
  84. if(outLog.is_open())
  85. {
  86. timeStamp(&outLog);
  87. outLog << "can not connect to ldap server in SyncPasswords" << endl;
  88. }
  89. result = -1;
  90. goto exit;
  91. }
  92. ourPasswordHandler.LoadSet(dataFilename);
  93. while(ourPasswordHandler.PeekUserPass(username, password) == 0)
  94. {
  95. if(QueryUsername(username) != 0)
  96. {
  97. // ToDo: generate event search failure.
  98. if(outLog.is_open())
  99. {
  100. timeStamp(&outLog);
  101. outLog << "search for " << username << " failed in SyncPasswords" << endl;
  102. }
  103. }
  104. else
  105. {
  106. while((dn = GetDN()) != NULL)
  107. {
  108. if(ModifyPassword(dn, password) != 0)
  109. {
  110. // ToDo: generate event modify failure.
  111. if(outLog.is_open())
  112. {
  113. timeStamp(&outLog);
  114. outLog << "modify password for " << username << " failed in SyncPasswords" << endl;
  115. }
  116. }
  117. else
  118. {
  119. if(outLog.is_open())
  120. {
  121. timeStamp(&outLog);
  122. outLog << "password for " << username << " modified" << endl;
  123. outLog << "\t" << dn << endl;
  124. }
  125. }
  126. }
  127. }
  128. // ToDo: zero out buffers
  129. ourPasswordHandler.PopUserPass();
  130. }
  131. ourPasswordHandler.SaveSet(dataFilename);
  132. Disconnect();
  133. exit:
  134. return result;
  135. }
  136. void PassSyncService::OnStop()
  137. {
  138. isRunning = false;
  139. SetEvent(passhookEventHandle);
  140. }
  141. void PassSyncService::OnShutdown()
  142. {
  143. isRunning = false;
  144. SetEvent(passhookEventHandle);
  145. }
  146. void PassSyncService::Run()
  147. {
  148. isRunning = true;
  149. SyncPasswords();
  150. while(isRunning)
  151. {
  152. WaitForSingleObject(passhookEventHandle, INFINITE);
  153. SyncPasswords();
  154. ResetEvent(passhookEventHandle);
  155. }
  156. }
  157. int PassSyncService::Connect()
  158. {
  159. int result = 0;
  160. if(ldapssl_client_init(certPath, &certdbh) != 0)
  161. {
  162. result = PR_GetError();
  163. if(outLog.is_open())
  164. {
  165. timeStamp(&outLog);
  166. outLog << "ldapssl_client_init failed in Connect" << endl;
  167. outLog << "\t" << result << ": " << ldapssl_err2string(result) << endl;
  168. }
  169. result = GetLastError();
  170. result = -1;
  171. goto exit;
  172. }
  173. pLdapConnection = ldapssl_init(ldapHostName, atoi(ldapHostPort), 1);
  174. if(pLdapConnection == NULL)
  175. {
  176. if(outLog.is_open())
  177. {
  178. timeStamp(&outLog);
  179. outLog << "ldapssl_init failed in Connect" << endl;
  180. }
  181. result = -1;
  182. goto exit;
  183. }
  184. lastLdapError = ldap_simple_bind_s(pLdapConnection, ldapAuthUsername, ldapAuthPassword);
  185. if(lastLdapError != LDAP_SUCCESS)
  186. {
  187. // ToDo: log reason for bind failure.
  188. if(outLog.is_open())
  189. {
  190. timeStamp(&outLog);
  191. outLog << "ldap error in Connect" << endl;
  192. outLog << "\t" << lastLdapError << ": " << ldapssl_err2string(lastLdapError) << endl;
  193. }
  194. result = -1;
  195. goto exit;
  196. }
  197. exit:
  198. return result;
  199. }
  200. int PassSyncService::Disconnect()
  201. {
  202. ldap_unbind(pLdapConnection);
  203. pLdapConnection = NULL;
  204. return 0;
  205. }
  206. int PassSyncService::QueryUsername(char* username)
  207. {
  208. int result = 0;
  209. char searchFilter[SYNCSERV_BUF_SIZE];
  210. results = NULL;
  211. _snprintf(searchFilter, SYNCSERV_BUF_SIZE, "(%s=%s)", ldapUsernameField, username);
  212. lastLdapError = ldap_search_ext_s(
  213. pLdapConnection,
  214. ldapSearchBase,
  215. LDAP_SCOPE_ONELEVEL,
  216. searchFilter,
  217. NULL,
  218. 0,
  219. NULL,
  220. NULL,
  221. NULL,
  222. -1,
  223. &results);
  224. if(lastLdapError != LDAP_SUCCESS)
  225. {
  226. // ToDo: log reason for search failure.
  227. if(outLog.is_open())
  228. {
  229. timeStamp(&outLog);
  230. outLog << "ldap error in QueryUsername" << endl;
  231. outLog << "\t" << lastLdapError << ": " << ldapssl_err2string(lastLdapError) << endl;
  232. }
  233. result = -1;
  234. goto exit;
  235. }
  236. exit:
  237. return result;
  238. }
  239. char* PassSyncService::GetDN()
  240. {
  241. char* result = NULL;
  242. if(multipleModify)
  243. {
  244. if(currentResult == NULL)
  245. {
  246. currentResult = ldap_first_entry(pLdapConnection, results);
  247. }
  248. else
  249. {
  250. currentResult = ldap_next_entry(pLdapConnection, currentResult);
  251. }
  252. result = ldap_get_dn(pLdapConnection, currentResult);
  253. }
  254. else
  255. {
  256. if(currentResult == NULL)
  257. {
  258. currentResult = ldap_first_entry(pLdapConnection, results);
  259. if(ldap_next_entry(pLdapConnection, currentResult) != NULLMSG)
  260. {
  261. // Too many results
  262. if(outLog.is_open())
  263. {
  264. timeStamp(&outLog);
  265. outLog << "too many results in GetDN" << endl;
  266. }
  267. currentResult = NULL;
  268. goto exit;
  269. }
  270. result = ldap_get_dn(pLdapConnection, currentResult);
  271. }
  272. else
  273. {
  274. currentResult = NULL;
  275. goto exit;
  276. }
  277. }
  278. exit:
  279. return result;
  280. }
  281. int PassSyncService::ModifyPassword(char* dn, char* password)
  282. {
  283. int result = 0;
  284. LDAPMod passMod;
  285. LDAPMod* mods[2] = {&passMod, NULL};
  286. char* modValues[2] = {password, NULL};
  287. passMod.mod_type = ldapPasswordField;
  288. passMod.mod_op = LDAP_MOD_REPLACE;
  289. passMod.mod_values = modValues;
  290. lastLdapError = ldap_modify_ext_s(pLdapConnection, dn, mods, NULL, NULL);
  291. if(lastLdapError != LDAP_SUCCESS)
  292. {
  293. // ToDo: log the reason for the modify failure.
  294. if(outLog.is_open())
  295. {
  296. timeStamp(&outLog);
  297. outLog << "ldap error in ModifyPassword" << endl;
  298. outLog << "\t" << lastLdapError << ": " << ldapssl_err2string(lastLdapError) << endl;
  299. }
  300. result = -1;
  301. }
  302. return result;
  303. }