UnixUserPlugin.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
  1. /*
  2. * Copyright 2005 - 2016 Zarafa and its licensors
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU Affero General Public License, version 3,
  6. * as published by the Free Software Foundation.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU Affero General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU Affero General Public License
  14. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. *
  16. */
  17. // -*- Mode: c++ -*-
  18. #ifndef UNIXUSERPLUGIN_H
  19. #define UNIXUSERPLUGIN_H
  20. #include <memory>
  21. #include <mutex>
  22. #include <string>
  23. #include <kopano/zcdefs.h>
  24. #include <kopano/ECIConv.h>
  25. #include "plugin.h"
  26. #include "DBBase.h"
  27. /**
  28. * @defgroup userplugin_unix UNIX user plugin
  29. * @ingroup userplugin
  30. * @{
  31. */
  32. namespace KC {
  33. /**
  34. * UNIX user plugin
  35. *
  36. * User management based on Unix. It uses /etc/passwd for the
  37. * loginname, fullname; and /etc/shadow for the password. Because it
  38. * needs to read /etc/shadow the server needs to run as a member of
  39. * the shadow group. When password updates need to be done, root
  40. * privileges are required.
  41. *
  42. * Extra attributes, such as email addresses, are stored in the objectproperty
  43. * tables, which are always present. It's exactly the same as the DBUserPlugin.
  44. */
  45. class UnixUserPlugin: public DBPlugin {
  46. public:
  47. /**
  48. * @param[in] pluginlock
  49. * The plugin mutex
  50. * @param[in] lpSharedData
  51. * The singleton shared plugin data.
  52. * @throw runtime_error When configuration file could not be loaded
  53. * @throw notsupported When multi-server or multi-company support is enabled.
  54. */
  55. UnixUserPlugin(std::mutex &, ECPluginSharedData *lpSharedData);
  56. virtual ~UnixUserPlugin();
  57. /**
  58. * Initialize plugin
  59. */
  60. void InitPlugin();
  61. /**
  62. * Resolve name and company to objectsignature
  63. *
  64. * @param[in] objclass
  65. * The objectclass of the name which should be resolved.
  66. * The objectclass can be partially unknown (OBJECTCLASS_UNKNOWN, MAILUSER_UNKNOWN, ...)
  67. * @param[in] name
  68. * The name which should be resolved
  69. * @param[in] company
  70. * The company beneath which the name should be searched
  71. * This objectid can be empty.
  72. * @return The object signature of the resolved object
  73. * @throw toomanyobjects When more then one object was found.
  74. * @throw objectnotfound When no object was found.
  75. * @throw runtime_error When an unsupported objectclass was requested.
  76. */
  77. virtual objectsignature_t resolveName(objectclass_t objclass, const string &name, const objectid_t &company);
  78. /**
  79. * Authenticate user with username and password
  80. *
  81. * @param[in] username
  82. * The username of the user to be authenticated
  83. * @param[in] password
  84. * The password of the user to be authenticated
  85. * @param[in] company
  86. * The objectid of the company to which the user belongs.
  87. * This objectid can be empty.
  88. * @return The objectsignature of the authenticated user
  89. * @throw objectnotfound When no user with the given name exists.
  90. * @throw login_error When the wrong password is provied or the user is nonactive.
  91. */
  92. virtual objectsignature_t authenticateUser(const string &username, const string &password, const objectid_t &company);
  93. /**
  94. * Request a list of objects for a particular company and specified objectclass.
  95. *
  96. * @param[in] company
  97. * The company beneath which the objects should be listed.
  98. * This objectid can be empty.
  99. * @param[in] objclass
  100. * The objectclass of the objects which should be returned.
  101. * The objectclass can be partially unknown (OBJECTCLASS_UNKNOWN, MAILUSER_UNKNOWN, ...)
  102. * @return The list of object signatures of all objects which were found
  103. * @throw std::exception
  104. */
  105. virtual std::unique_ptr<signatures_t> getAllObjects(const objectid_t &company, objectclass_t objclass);
  106. /**
  107. * Obtain the object details for the given object
  108. *
  109. * Besides the information from Unix, the details will also
  110. * be merged with details from DBPlugin::getObjectDetails()
  111. *
  112. * @param[in] objectid
  113. * The objectid for which is details are requested
  114. * @return The objectdetails for the given objectid
  115. * @throw std::exception
  116. */
  117. virtual std::unique_ptr<objectdetails_t> getObjectDetails(const objectid_t &objectid);
  118. /**
  119. * Obtain the object details for the given objects
  120. *
  121. * This will loop through the list of objectids and call
  122. * UnixUserPlugin::getObjectDetails(const objectid_t &objectid) for each objectid.
  123. *
  124. * @param[in] objectids
  125. * The list of object signatures for which the details are requested
  126. * @return A map of objectid with the matching objectdetails
  127. * @throw std::exception
  128. */
  129. virtual std::unique_ptr<std::map<objectid_t, objectdetails_t> > getObjectDetails(const std::list<objectid_t> &objectids);
  130. /**
  131. * Get all children for a parent for a given relation type.
  132. * For example all users in a group
  133. *
  134. * OBJECTRELATION_GROUP_MEMBER will be queried to Unix directly, for
  135. * all other relations DBPlugin::getSubObjectsForObject() is called.
  136. *
  137. * @param[in] relation
  138. * The relation type which connects the child and parent object
  139. * @param[in] parentobject
  140. * The parent object for which the children are requested
  141. * @return A list of object signatures of the children of the parent.
  142. * @throw std::exception
  143. */
  144. virtual std::unique_ptr<signatures_t> getSubObjectsForObject(userobject_relation_t relation, const objectid_t &parentobject);
  145. /**
  146. * Request all parents for a childobject for a given relation type.
  147. * For example all groups for a user
  148. *
  149. * OBJECTRELATION_GROUP_MEMBER will be queried to Unix directly, for
  150. * all other relations DBPlugin::getParentObjectsForObject() is called.
  151. *
  152. * @param[in] relation
  153. * The relation type which connects the child and parent object
  154. * @param[in] childobject
  155. * The childobject for which the parents are requested
  156. * @return A list of object signatures of the parents of the child.
  157. * @throw std::exception
  158. */
  159. virtual std::unique_ptr<signatures_t> getParentObjectsForObject(userobject_relation_t relation, const objectid_t &childobject);
  160. /**
  161. * Search for all objects which match the given string,
  162. * the name and email address should be compared for this search.
  163. *
  164. * Besides checking Unix information, the email address is also checked by calling
  165. * DBPlugin::searchObjects().
  166. *
  167. * @param[in] match
  168. * The string which should be found
  169. * @param[in] ulFlags
  170. * If EMS_AB_ADDRESS_LOOKUP the string must exactly match the name or email address
  171. * otherwise a partial match is allowed.
  172. * @return List of object signatures which match the given string
  173. * @throw objectnotfound When no object was found
  174. */
  175. virtual std::unique_ptr<signatures_t> searchObject(const std::string &match, unsigned int ulFlags);
  176. /**
  177. * Obtain details for the public store
  178. *
  179. * @note This function has not been implemented and will always throw an exception.
  180. *
  181. * @return The public store details
  182. * @throw notsupported Always when this function is called
  183. */
  184. virtual std::unique_ptr<objectdetails_t> getPublicStoreDetails(void);
  185. /**
  186. * Obtain the objectdetails for a server
  187. *
  188. * @note This function has not been implemented and will always throw an exception.
  189. *
  190. * @param[in] server
  191. * The externid of the server
  192. * @return The server details
  193. * @throw notsupported Always when this function is called
  194. */
  195. virtual std::unique_ptr<serverdetails_t> getServerDetails(const std::string &server);
  196. /**
  197. * Obtain server list
  198. *
  199. * @return list of servers
  200. * @throw runtime_error LDAP query failure
  201. */
  202. virtual std::unique_ptr<serverlist_t> getServers(void);
  203. /**
  204. * Create object in plugin
  205. *
  206. * @note This function has not been implemented and will always throw an exception.
  207. *
  208. * @param[in] details
  209. * The object details of the new object.
  210. * @return The objectsignature of the created object.
  211. * @throw notimplemented Always when this function is called
  212. */
  213. virtual objectsignature_t createObject(const objectdetails_t &details);
  214. /**
  215. * Update an object with new details
  216. *
  217. * Does not support changing OB_PROP_S_PASSWORD, OB_PROP_S_LOGIN and OB_PROP_S_FULLNAME,
  218. * all other details are updated by calling DBPlugin::changeObject().
  219. *
  220. * @param[in] id
  221. * The object id of the object which should be updated.
  222. * @param[in] details
  223. * The objectdetails which should be written to the object.
  224. * @param[in] lpRemove
  225. * List of configuration names which should be removed from the object
  226. * @throw runtime_error When OB_PROP_S_PASSWORD, OB_PROP_S_LOGIN, OB_PROP_S_FULLNAME or is non-empty.
  227. */
  228. virtual void changeObject(const objectid_t &id, const objectdetails_t &details, const std::list<std::string> *lpRemove);
  229. /**
  230. * Delete object from plugin
  231. *
  232. * @note This function has not been implemented and will always throw an exception.
  233. *
  234. * @param[in] id
  235. * The objectid which should be deleted
  236. * @throw notimplemented Always when this function is called
  237. */
  238. virtual void deleteObject(const objectid_t &id);
  239. /**
  240. * Modify id of object in plugin
  241. *
  242. * @note This function is not supported by this plugin and will always throw an exception
  243. *
  244. * @param[in] oldId
  245. * The old objectid
  246. * @param[in] newId
  247. * The new objectid
  248. * @throw notsupported Always when this function is called
  249. */
  250. virtual void modifyObjectId(const objectid_t &oldId, const objectid_t &newId);
  251. /**
  252. * Add relation between child and parent. This can be used
  253. * for example to add a user to a group or add
  254. * permission relations on companies.
  255. *
  256. * Only OBJECTRELATION_QUOTA_USERRECIPIENT and OBJECTRELATION_USER_SENDAS
  257. * are supported. All other relation types are forwarded to
  258. * DBPlugin::addSubObjectRelation()
  259. *
  260. * @param[in] relation
  261. * The relation type which should connect the child and parent.
  262. * @param[in] parentobject
  263. * The parent object.
  264. * @param[in] childobject
  265. * The child object.
  266. * @throw notimplemented when an unsupported relation is requested
  267. */
  268. virtual void addSubObjectRelation(userobject_relation_t relation,
  269. const objectid_t &parentobject, const objectid_t &childobject);
  270. /**
  271. * Delete relation between child and parent, this can be used
  272. * for example to delete a user from a group or delete
  273. * permission relations on companies.
  274. *
  275. * Only OBJECTRELATION_QUOTA_USERRECIPIENT and OBJECTRELATION_USER_SENDAS
  276. * are supported. All other relation types are forwarded to
  277. * DBPlugin::deleteSubObjectRelation().
  278. *
  279. * @param[in] relation
  280. * The relation type which connected the child and parent.
  281. * @param[in] parentobject
  282. * The parent object.
  283. * @param[in] childobject
  284. * The child object.
  285. * @throw notimplemented when an unsupported relation is requested
  286. */
  287. virtual void deleteSubObjectRelation(userobject_relation_t relation,
  288. const objectid_t &parentobject, const objectid_t &childobject);
  289. private:
  290. ECIConv *m_iconv = nullptr;
  291. /**
  292. * Find a user with specific name
  293. *
  294. * @param[in] id
  295. * The id of the user which must be found
  296. * @param[out] pwd
  297. * The found passwd structure
  298. * @param[out] buffer
  299. * A buffer which will contain the strings for pwd
  300. * @throw objectnotfound If no user was found.
  301. */
  302. void findUserID(const string &id, struct passwd *pwd, char *buffer);
  303. /**
  304. * Find a user with specific name
  305. *
  306. * @param[in] name
  307. * The name of the user which must be found
  308. * @param[out] pwd
  309. * The found passwd structure
  310. * @param[out] buffer
  311. * A buffer which will contain the strings for pwd
  312. * @throw objectnotfound If no user was found.
  313. */
  314. void findUser(const string &name, struct passwd *pwd, char *buffer);
  315. /**
  316. * Find a group with specific ID
  317. *
  318. * @param[in] id
  319. * The id of the group which must be found
  320. * @param[out] grp
  321. * The found group structure
  322. * @param[out] buffer
  323. * A buffer which will contain the strings for grp
  324. * @throw objectnotfound If no group was found.
  325. */
  326. void findGroupID(const string &id, struct group *grp, char *buffer);
  327. /**
  328. * Find a group with specific name
  329. *
  330. * @param[in] name
  331. * The name of the group which must be found
  332. * @param[out] grp
  333. * The found group structure
  334. * @param[out] buffer
  335. * A buffer which will contain the strings for grp
  336. * @throw objectnotfound If no group was found.
  337. */
  338. void findGroup(const string &name, struct group *grp, char *buffer);
  339. /**
  340. * Resolve user name to objectsignature
  341. *
  342. * This will call UnixUserPlugin::findUser()
  343. *
  344. * @param[in] name
  345. * Name of the user which must be found
  346. * @return The objectsignature of the resolved object
  347. * @throw std::exception
  348. */
  349. objectsignature_t resolveUserName(const string &name);
  350. /**
  351. * Resolve group name to objectsignature
  352. *
  353. * This will call UnixUserPlugin::findGroup()
  354. *
  355. * @param[in] name
  356. * Name of the group which must be found
  357. * @return The objectsignature of the resolved object
  358. * @throw std::exception
  359. */
  360. objectsignature_t resolveGroupName(const string &name);
  361. /**
  362. * Match a user with given search query
  363. *
  364. * @param[in] pw
  365. * The user which should be checked
  366. * @param[in] match
  367. * Check if the term matches the user pw
  368. * @param[in] ulFlags
  369. * If EMS_AB_ADDRESS_LOOKUP the string must exactlymatch the name or
  370. * email address otherwise a partial match is allowed.
  371. * @return True if the user matches the query
  372. */
  373. bool matchUserObject(struct passwd *pw, const string &match, unsigned int ulFlags);
  374. /**
  375. * Match a group with given search query
  376. *
  377. * @param[in] gr
  378. * The group which should be checked
  379. * @param[in] match
  380. * Check if the term matches the group gr
  381. * @param[in] ulFlags
  382. * If EMS_AB_ADDRESS_LOOKUP the string must exactlymatch the name or
  383. * email address otherwise a partial match is allowed.
  384. * @return True if the group matches the query
  385. */
  386. bool matchGroupObject(struct group *gr, const string &match, unsigned int ulFlags);
  387. /**
  388. * Create a list containing all users which optionally match the search term.
  389. *
  390. * @param[in] match
  391. * Optional parameter. Search for all users which match the term
  392. * @param[in] ulFlags
  393. * Optional parameter. If EMS_AB_ADDRESS_LOOKUP the string must exactly
  394. * match the name or email address otherwise a partial match is allowed.
  395. * @return List of objectsignatures
  396. */
  397. std::unique_ptr<signatures_t> getAllUserObjects(const std::string &match = std::string(), unsigned int ulFlags = 0);
  398. /**
  399. * Create a list containing all groups which optionally match the search term.
  400. *
  401. * @param[in] match
  402. * Optional parameter. Search for all groups which match the term
  403. * @param[in] ulFlags
  404. * Optional parameter. If EMS_AB_ADDRESS_LOOKUP the string must exactly
  405. * match the name or email address otherwise a partial match is allowed.
  406. * @return List of objectsignatures
  407. */
  408. std::unique_ptr<signatures_t> getAllGroupObjects(const std::string &match = std::string(), unsigned int ulFlags = 0);
  409. /**
  410. * Copy object details from struct passwd to objectdetails
  411. *
  412. * @param[in] pw
  413. * Pointer to struct pw from which the details must be collected
  414. * @return The objectdetails which were collected from pw
  415. */
  416. std::unique_ptr<objectdetails_t> objectdetailsFromPwent(struct passwd *pw); // PAM part
  417. /**
  418. * Copy object details from struct group to objectdetails
  419. *
  420. * @param[in] gr
  421. * Pointer to struct group from which the details must be collected
  422. * @return The objectdetails which were collected from gr
  423. */
  424. std::unique_ptr<objectdetails_t> objectdetailsFromGrent(struct group *gr);
  425. /**
  426. * Query the Database to obtain the signature for the objectid.
  427. *
  428. * @param[in] id
  429. * The object for which the signature is requested
  430. * @return the object signature
  431. */
  432. std::string getDBSignature(const objectid_t &id);
  433. /**
  434. * Check errno for errors which should trigger an exception
  435. *
  436. * @param[in] user
  437. * The username for which the exception will be thrown.
  438. * @throw runtime_error Thrown when errno was set.
  439. */
  440. void errnoCheck(const std::string &, int) const;
  441. };
  442. } /* namespace */
  443. extern "C" {
  444. extern _kc_export UserPlugin *getUserPluginInstance(std::mutex &, ECPluginSharedData *);
  445. extern _kc_export void deleteUserPluginInstance(UserPlugin *);
  446. extern _kc_export int getUserPluginVersion(void);
  447. }
  448. /** @} */
  449. #endif