PageRenderTime 46ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/nxmydb/tags/0.1.0/source/user.c

http://nxscripts.googlecode.com/
C | 395 lines | 265 code | 77 blank | 53 comment | 76 complexity | 3b9c3a2cd5b4936705c70d4335600897 MD5 | raw file
Possible License(s): LGPL-2.1, BSD-3-Clause
  1. /*
  2. nxMyDB - MySQL Database for ioFTPD
  3. Copyright (c) 2006-2007 neoxed
  4. Module Name:
  5. User Module
  6. Author:
  7. neoxed (neoxed@gmail.com) Jun 3, 2006
  8. Abstract:
  9. Entry point and functions for the user module.
  10. */
  11. #include <base.h>
  12. #include <backends.h>
  13. #include <database.h>
  14. static INT UserFinalize(VOID);
  15. static INT32 UserCreate(CHAR *userName);
  16. static INT UserRename(CHAR *userName, INT32 userId, CHAR *newName);
  17. static INT UserDelete(CHAR *userName, INT32 userId);
  18. static INT UserLock(USERFILE *userFile);
  19. static INT UserUnlock(USERFILE *userFile);
  20. static INT UserOpen(CHAR *userName, USERFILE *userFile);
  21. static INT UserWrite(USERFILE *userFile);
  22. static INT UserClose(USERFILE *userFile);
  23. static USER_MODULE *userModule = NULL;
  24. INT UserModuleInit(USER_MODULE *module)
  25. {
  26. // Initialize module structure
  27. module->tszModuleName = "NXMYDB";
  28. module->DeInitialize = UserFinalize;
  29. module->Create = UserCreate;
  30. module->Rename = UserRename;
  31. module->Delete = UserDelete;
  32. module->Lock = UserLock;
  33. module->Unlock = UserUnlock;
  34. module->Open = UserOpen;
  35. module->Write = UserWrite;
  36. module->Close = UserClose;
  37. // Initialize module
  38. if (!DbInit(module->GetProc)) {
  39. TRACE("Unable to initialize module.\n");
  40. return UM_ERROR;
  41. }
  42. userModule = module;
  43. return UM_SUCCESS;
  44. }
  45. static INT UserFinalize(VOID)
  46. {
  47. DbFinalize();
  48. userModule = NULL;
  49. return UM_SUCCESS;
  50. }
  51. static INT32 UserCreate(CHAR *userName)
  52. {
  53. DB_CONTEXT *db;
  54. MOD_CONTEXT *mod;
  55. DWORD result;
  56. INT32 userId = -1;
  57. USERFILE userFile;
  58. TRACE("userName=%s\n", userName);
  59. if (!DbAcquire(&db)) {
  60. return userId;
  61. }
  62. // Module context is required for all file operations
  63. mod = Io_Allocate(sizeof(MOD_CONTEXT));
  64. if (mod == NULL) {
  65. result = ERROR_NOT_ENOUGH_MEMORY;
  66. TRACE("Unable to allocate module context.\n");
  67. } else {
  68. // Initialize MOD_CONTEXT structure
  69. mod->file = INVALID_HANDLE_VALUE;
  70. // Initialize USERFILE structure
  71. ZeroMemory(&userFile, sizeof(USERFILE));
  72. userFile.Groups[0] = NOGROUP_ID;
  73. userFile.Groups[1] = -1;
  74. userFile.AdminGroups[0] = -1;
  75. userFile.lpInternal = mod;
  76. // Read "Default.User" file
  77. result = FileUserDefault(&userFile);
  78. if (result != ERROR_SUCCESS) {
  79. TRACE("Unable to read \"Default.User\" file (error %lu).\n", result);
  80. }
  81. // Register user
  82. userId = userModule->Register(userModule, userName, &userFile);
  83. if (userId == -1) {
  84. result = GetLastError();
  85. TRACE("Unable to register user (error %lu).\n", result);
  86. } else {
  87. // Create user file
  88. result = FileUserCreate(userId, &userFile);
  89. if (result != ERROR_SUCCESS) {
  90. TRACE("Unable to create user file (error %lu).\n", result);
  91. } else {
  92. // Create database record
  93. result = DbUserCreate(db, userName, &userFile);
  94. if (result != ERROR_SUCCESS) {
  95. TRACE("Unable to create database record (error %lu).\n", result);
  96. }
  97. }
  98. // If the file or database creation failed, clean-up the user file
  99. if (result != ERROR_SUCCESS) {
  100. userModule->Unregister(userModule, userName);
  101. FileUserDelete(userId);
  102. FileUserClose(&userFile);
  103. }
  104. }
  105. if (result != ERROR_SUCCESS) {
  106. // Free module context after all file operations
  107. Io_Free(mod);
  108. // Indicate an error occured by returning an invalid user ID
  109. userId = -1;
  110. }
  111. }
  112. DbRelease(db);
  113. SetLastError(result);
  114. return userId;
  115. }
  116. static INT UserRename(CHAR *userName, INT32 userId, CHAR *newName)
  117. {
  118. DB_CONTEXT *db;
  119. DWORD result;
  120. UNREFERENCED_PARAMETER(userId);
  121. TRACE("userName=%s userId=%d newName=%s\n", userName, userId, newName);
  122. if (!DbAcquire(&db)) {
  123. return UM_ERROR;
  124. }
  125. // Rename database record
  126. result = DbUserRename(db, userName, newName);
  127. if (result != ERROR_SUCCESS) {
  128. TRACE("Unable to rename user database record (error %lu).\n", result);
  129. } else {
  130. // Register user under the new name
  131. if (userModule->RegisterAs(userModule, userName, newName) != UM_SUCCESS) {
  132. result = GetLastError();
  133. TRACE("Unable to re-register user (error %lu).\n", result);
  134. }
  135. }
  136. DbRelease(db);
  137. SetLastError(result);
  138. return (result == ERROR_SUCCESS) ? UM_SUCCESS : UM_ERROR;
  139. }
  140. static INT UserDelete(CHAR *userName, INT32 userId)
  141. {
  142. DB_CONTEXT *db;
  143. DWORD result;
  144. TRACE("userName=%s userId=%d\n", userName, userId);
  145. if (!DbAcquire(&db)) {
  146. return UM_ERROR;
  147. }
  148. // Delete user file (success does not matter)
  149. result = FileUserDelete(userId);
  150. if (result != ERROR_SUCCESS) {
  151. TRACE("Unable to delete user file (error %lu).\n", result);
  152. }
  153. // Delete database record
  154. result = DbUserDelete(db, userName);
  155. if (result != ERROR_SUCCESS) {
  156. TRACE("Unable to delete user database record (error %lu).\n", result);
  157. } else {
  158. // Unregister user
  159. if (userModule->Unregister(userModule, userName) != UM_SUCCESS) {
  160. result = GetLastError();
  161. TRACE("Unable to unregister user (error %lu).\n", result);
  162. }
  163. }
  164. DbRelease(db);
  165. SetLastError(result);
  166. return (result == ERROR_SUCCESS) ? UM_SUCCESS : UM_ERROR;
  167. }
  168. static INT UserLock(USERFILE *userFile)
  169. {
  170. CHAR *userName;
  171. DB_CONTEXT *db;
  172. DWORD result;
  173. TRACE("userFile=%p\n", userFile);
  174. if (!DbAcquire(&db)) {
  175. return UM_ERROR;
  176. }
  177. // Resolve user ID to user name
  178. userName = Io_Uid2User(userFile->Uid);
  179. if (userName == NULL) {
  180. result = ERROR_ID_NOT_FOUND;
  181. } else {
  182. // Lock user
  183. result = DbUserLock(db, userName, userFile);
  184. if (result != ERROR_SUCCESS) {
  185. TRACE("Unable to lock user (error %lu).\n", result);
  186. }
  187. }
  188. DbRelease(db);
  189. SetLastError(result);
  190. return (result == ERROR_SUCCESS) ? UM_SUCCESS : UM_ERROR;
  191. }
  192. static INT UserUnlock(USERFILE *userFile)
  193. {
  194. CHAR *userName;
  195. DB_CONTEXT *db;
  196. DWORD result;
  197. TRACE("userFile=%p\n", userFile);
  198. if (!DbAcquire(&db)) {
  199. return UM_ERROR;
  200. }
  201. // Resolve user ID to user name
  202. userName = Io_Uid2User(userFile->Uid);
  203. if (userName == NULL) {
  204. result = ERROR_ID_NOT_FOUND;
  205. } else {
  206. // Unlock user
  207. result = DbUserUnlock(db, userName);
  208. if (result != ERROR_SUCCESS) {
  209. TRACE("Unable to unlock user (error %lu).\n", result);
  210. }
  211. }
  212. DbRelease(db);
  213. SetLastError(result);
  214. return (result == ERROR_SUCCESS) ? UM_SUCCESS : UM_ERROR;
  215. }
  216. static INT UserOpen(CHAR *userName, USERFILE *userFile)
  217. {
  218. DB_CONTEXT *db;
  219. DWORD result;
  220. MOD_CONTEXT *mod;
  221. TRACE("userName=%s userFile=%p\n", userName, userFile);
  222. if (!DbAcquire(&db)) {
  223. return UM_ERROR;
  224. }
  225. // Module context is required for all file operations
  226. mod = Io_Allocate(sizeof(MOD_CONTEXT));
  227. if (mod == NULL) {
  228. result = ERROR_NOT_ENOUGH_MEMORY;
  229. TRACE("Unable to allocate module context.\n");
  230. } else {
  231. // Initialize MOD_CONTEXT structure
  232. mod->file = INVALID_HANDLE_VALUE;
  233. userFile->lpInternal = mod;
  234. // Open user file
  235. result = FileUserOpen(userFile->Uid, userFile);
  236. if (result != ERROR_SUCCESS) {
  237. TRACE("Unable to open user file (error %lu).\n", result);
  238. } else {
  239. // Read database record
  240. result = DbUserOpen(db, userName, userFile);
  241. if (result != ERROR_SUCCESS) {
  242. TRACE("Unable to open user database record (error %lu).\n", result);
  243. // Clean-up user file
  244. FileUserClose(userFile);
  245. }
  246. }
  247. // Free module context if the file/database open failed
  248. if (result != ERROR_SUCCESS) {
  249. Io_Free(mod);
  250. }
  251. }
  252. DbRelease(db);
  253. //
  254. // Return UM_DELETED instead of UM_ERROR to work around a bug in ioFTPD. If
  255. // UM_ERROR is returned, ioFTPD frees part of the USERFILE structure and
  256. // may crash later on (e.g. if someone issues "SITE USERS").
  257. //
  258. SetLastError(result);
  259. return (result == ERROR_SUCCESS) ? UM_SUCCESS : UM_DELETED;
  260. }
  261. static INT UserWrite(USERFILE *userFile)
  262. {
  263. CHAR *userName;
  264. DB_CONTEXT *db;
  265. DWORD result;
  266. TRACE("userFile=%p\n", userFile);
  267. if (!DbAcquire(&db)) {
  268. return UM_ERROR;
  269. }
  270. // Update user file (success does not matter)
  271. result = FileUserWrite(userFile);
  272. if (result != ERROR_SUCCESS) {
  273. TRACE("Unable to write user file (error %lu).\n", result);
  274. }
  275. // Resolve user ID to user name
  276. userName = Io_Uid2User(userFile->Uid);
  277. if (userName == NULL) {
  278. result = ERROR_ID_NOT_FOUND;
  279. } else {
  280. // Update user database record
  281. result = DbUserWrite(db, userName, userFile);
  282. if (result != ERROR_SUCCESS) {
  283. TRACE("Unable to write user database record (error %lu).\n", result);
  284. }
  285. }
  286. DbRelease(db);
  287. SetLastError(result);
  288. return (result == ERROR_SUCCESS) ? UM_SUCCESS : UM_ERROR;
  289. }
  290. static INT UserClose(USERFILE *userFile)
  291. {
  292. DWORD result;
  293. MOD_CONTEXT *mod;
  294. TRACE("userFile=%p\n", userFile);
  295. mod = userFile->lpInternal;
  296. if (mod != NULL) {
  297. // Close user file (success does not matter)
  298. result = FileUserClose(userFile);
  299. if (result != ERROR_SUCCESS) {
  300. TRACE("Unable to close user file (error %lu).\n", result);
  301. }
  302. // Close user database record (success does not matter)
  303. result = DbUserClose(userFile);
  304. if (result != ERROR_SUCCESS) {
  305. TRACE("Unable to close user database record (error %lu).\n", result);
  306. }
  307. // Free module context
  308. Io_Free(mod);
  309. userFile->lpInternal = NULL;
  310. }
  311. return UM_SUCCESS;
  312. }