ipcd.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847
  1. #include <stdio.h>
  2. #include <errno.h>
  3. #include <unistd.h>
  4. #include <sys/prctl.h>
  5. #include "auth.h"
  6. #include "driver.h"
  7. #include "ipc.h"
  8. #include "fingerdb.h"
  9. /********************************
  10. * *
  11. * This file contents *
  12. * server-side IPC functions *
  13. * *
  14. ********************************/
  15. /***************************
  16. * UTILS *
  17. ***************************/
  18. /**********************************************************************
  19. func waitSemaphoreWhileSocket
  20. wait semaphore and monitor socket at same time
  21. input
  22. sem - semaphore which need wait
  23. soc - socket which need monitor
  24. return
  25. 0 if semaphore has been got
  26. -ECONNRESET on socket drop
  27. negative on error
  28. ***********************************************************************/
  29. static int waitSemaphoreWhileSocket( sem_t* sem, int soc ){
  30. struct timespec t;
  31. while( !write(soc, NULL, 0) ) {
  32. if( clock_gettime(CLOCK_REALTIME, &t) ){
  33. perror( "[ipcd] clock" );
  34. return -EINVAL;//clock error
  35. }
  36. t.tv_sec += 2;
  37. if( !sem_timedwait(sem, &t) ) return 0;//sem got
  38. else if( errno != ETIMEDOUT ){
  39. perror( "[ipcd] sem" );
  40. return -EINTR;//semaphore error
  41. }
  42. }
  43. perror( "[ipcd] sock" );
  44. return -ECONNRESET;//socket drop
  45. }
  46. static void driverSwitchMode( struct driverInstance* this, unsigned char mode ){
  47. if( this->modeIndicator == mode ) return;
  48. //switch mode
  49. this->modeSwitcher = mode;
  50. if( this->modeIndicator == MODE_IDLE ) sem_post( &this->semaphoreIdle );
  51. else if( this->modeIndicator == MODE_SCANNING && this->driverState == STATE_WAIT_IPC ){
  52. sem_post( &this->semaphoreScan );
  53. goto l_wait_enter;
  54. }
  55. //wait exit mode notification
  56. sem_wait( &this->semaphoreIpc );
  57. l_wait_enter: //wait enter mode notification
  58. sem_wait( &this->semaphoreIpc );
  59. }
  60. /************************************************
  61. func getFingerImageFromScanner
  62. scan finger and get fingerprint
  63. caller must switch mode after this
  64. proto:
  65. if driver send message to ipcd, ipcd send message to socket
  66. <IPC_DRIVER_MESSAGE> <message (unsigned char)>
  67. return
  68. 0 on success
  69. -ECONNRESET on socket drop or error
  70. any negative codes from fingerScanPolling
  71. *************************************************/
  72. static int getFingerImageFromScanner( struct driverInstance* this, int socket ){
  73. unsigned char driverMessage;
  74. if( this->modeIndicator != MODE_SCANNING ) driverSwitchMode( this, MODE_SCANNING );
  75. if( this->driverState == STATE_WAIT_IPC ) sem_post( &this->semaphoreScan );
  76. //prompt the user to swipe the scanner
  77. if( write(socket, &IPC_DRIVER_MESSAGE, 1) != 1 ) goto l_abort;
  78. if( write(socket, &IPC_PROMPT_SWIPE_SCANNER, 1) != 1 ) goto l_abort;
  79. l_waitSemaphore:
  80. //wait semaphore and monitor socket
  81. if( waitSemaphoreWhileSocket(&this->semaphoreIpc, socket) ) goto l_abort;
  82. if( this->scanResult > 0 ){//message from driver
  83. driverMessage = this->scanResult;
  84. if( write(socket, &IPC_DRIVER_MESSAGE, 1) != 1 ) goto l_abort;
  85. if( write(socket, &driverMessage, 1) != 1 ) goto l_abort;
  86. sem_post( &this->semaphoreScan );
  87. goto l_waitSemaphore;
  88. }
  89. //scan done or error
  90. return this->scanResult;
  91. l_abort: //tell driver abort
  92. this->modeSwitcher = MODE_IDLE;
  93. sem_wait( &this->semaphoreIpc );
  94. if( this->scanResult > 0 ){
  95. sem_post( &this->semaphoreScan );
  96. goto l_abort;
  97. }
  98. this->modeSwitcher = MODE_SCANNING;
  99. return -ECONNRESET;
  100. }
  101. /*
  102. send to socket:
  103. <length> [content]
  104. return
  105. ret = 0 - ok
  106. ret = -1 - wrong field type
  107. ret = -2 - db error
  108. ret = -3 - socket error
  109. */
  110. static int printFieldContentToSocket( int socket, int recordId, const struct ipc_field* field ){
  111. int value;
  112. int len;
  113. char buf[1024];
  114. //read data from db into buffer
  115. if( field->type == 'i' ){
  116. //read data as integer and convert to text
  117. len = fingerdbGetField( recordId, field->name, &value, sizeof(value) );
  118. if( len < 0 ) return -2;
  119. if( len > 0 ){
  120. sprintf( buf, "%i", value );
  121. len = strlen( buf );
  122. }
  123. }else if( field->type == 't' ){
  124. //read data as regular text
  125. len = fingerdbGetField( recordId, field->name, buf, 1024 );
  126. if( len < 0 ) return -2;
  127. buf[len] = 0x00;//make sure string is null-terminated
  128. }else return -1;
  129. //send data to socket
  130. if( write(socket, &len, sizeof(len)) != sizeof(len) ) goto l_perror;
  131. if( len > 0 ){
  132. if( write(socket, buf, len) != len ) goto l_perror;
  133. }
  134. return 0;
  135. l_perror:
  136. perror( "[ipcd]" );
  137. return -3;
  138. }
  139. /***************************
  140. * OPERATIONS *
  141. ***************************/
  142. /*
  143. request: <IPC_TOUCHPAD> <mode>
  144. response: <mode> || <IPC_ERROR>
  145. */
  146. static void touchpadControl( struct driverInstance* this, int socket ){
  147. unsigned char cmd;
  148. unsigned char ans;
  149. if( recv( socket, &cmd, 1, MSG_WAITALL) != 1 ) goto l_perror;
  150. if( cmd == IPC_TOUCHPAD_OFF ) driverSwitchMode( this, MODE_IDLE );
  151. else if( cmd != IPC_TOUCHPAD_STATUS ){
  152. if( this->modeIndicator != MODE_TOUCHPAD ){
  153. if( cmd == IPC_TOUCHPAD_MOUSE ) this->touchpadMode = MODE_TOUCHPAD_MOUSE;
  154. else if( cmd == IPC_TOUCHPAD_WHEELS ) this->touchpadMode = MODE_TOUCHPAD_WHEELS;
  155. else if( cmd == IPC_TOUCHPAD_ARROWS ) this->touchpadMode = MODE_TOUCHPAD_ARROWS;
  156. else{
  157. ans = IPC_ERROR;
  158. goto l_ans;
  159. }
  160. driverSwitchMode( this, MODE_TOUCHPAD );
  161. } else {
  162. if( cmd == IPC_TOUCHPAD_MOUSE ) this->modeSwitcher = MODE_TOUCHPAD_MOUSE;
  163. else if( cmd == IPC_TOUCHPAD_WHEELS ) this->modeSwitcher = MODE_TOUCHPAD_WHEELS;
  164. else if( cmd == IPC_TOUCHPAD_ARROWS ) this->modeSwitcher = MODE_TOUCHPAD_ARROWS;
  165. else{
  166. ans = IPC_ERROR;
  167. goto l_ans;
  168. }
  169. sem_wait( &this->semaphoreIpc );
  170. }
  171. }
  172. if( this->modeIndicator != MODE_TOUCHPAD ) ans = IPC_TOUCHPAD_OFF;
  173. else{
  174. if( this->touchpadMode == MODE_TOUCHPAD_MOUSE ) ans = IPC_TOUCHPAD_MOUSE;
  175. else if( this->touchpadMode == MODE_TOUCHPAD_WHEELS ) ans = IPC_TOUCHPAD_WHEELS;
  176. else if( this->touchpadMode == MODE_TOUCHPAD_ARROWS ) ans = IPC_TOUCHPAD_ARROWS;
  177. else ans = IPC_ERROR;
  178. }
  179. l_ans:
  180. if( write(socket, &ans, 1) != 1 ) goto l_perror;
  181. return;
  182. l_perror:
  183. perror( "[ipcd]" );
  184. }
  185. /*
  186. request: <IPC_USER_AUTH> <mode> <userlen(int)> <username>
  187. response: <IPC_SUCCESS> || <IPC_ERROR> || <IPC_DRIVER_MESSAGE> <MSG>
  188. also messages from driver
  189. */
  190. static void authUser( struct driverInstance* this, int socket ){
  191. int res;
  192. char username[40];
  193. int usernameLength;
  194. unsigned char savedMode;
  195. unsigned char foundFlag;
  196. unsigned char authMode;
  197. foundFlag = 0x00;
  198. savedMode = this->modeIndicator;
  199. //read auth mode
  200. if( recv(socket, &authMode, 1, MSG_WAITALL) != 1 ) goto l_perror;
  201. //username length receive and check
  202. if( recv(socket, &usernameLength, sizeof(usernameLength), MSG_WAITALL) != sizeof(usernameLength) ) goto l_perror;
  203. if( usernameLength < 1 || usernameLength > 32 ) goto l_sendResult;
  204. //username receive
  205. if( recv(socket, username, usernameLength, MSG_WAITALL) != usernameLength ) goto l_perror;
  206. username[usernameLength] = 0x00; //make sure string null-terminated
  207. if( authMode == IPC_USER_AUTH_ACTIVE ){//auth in active mode
  208. //scan finger
  209. res = getFingerImageFromScanner( this, socket );
  210. if( res == -ECONNRESET ) goto l_exit;
  211. if( res ) goto l_sendResult;
  212. //search match in finger db
  213. res = authSearchMatch( this->data, username );
  214. if( res > 0 ) foundFlag = 0xff;
  215. }else if( authMode == IPC_USER_AUTH_PASSIVE ){//auth in passive mode
  216. //check current state
  217. if( this->passiveAuthModeIndicator != PA_STOP ){
  218. printf( "[ipcd] ERROR: Unexpected passive auth state.\n" );
  219. goto l_sendResult;
  220. }
  221. //setup passive auth mode
  222. this->passiveAuthModeSwitcher = PA_START;
  223. //switch to idle
  224. driverSwitchMode( this, MODE_IDLE );
  225. //notise idle mode about passive auth start and wait response
  226. sem_post( &this->semaphoreIdle );
  227. sem_wait( &this->semaphoreIpc );
  228. //check response
  229. if( this->passiveAuthModeIndicator != PA_START ){
  230. printf( "[ipcd] FATAL ERROR: Passive auth start return unexpected response 0x%02x\n", this->passiveAuthModeIndicator );
  231. goto l_sendResult;
  232. }
  233. //set username for auth and signal to main thread for continue
  234. this->passiveAuthUsername = username;
  235. sem_post( &this->semaphoreScan );
  236. //prompt the user to swipe the scanner
  237. if( write(socket, &IPC_DRIVER_MESSAGE, 1) != 1 ) goto l_abort;
  238. if( write(socket, &IPC_PROMPT_SWIPE_SCANNER, 1) != 1 ) goto l_abort;
  239. //wait semaphore and monitor socket
  240. res = waitSemaphoreWhileSocket( &this->semaphoreIpc, socket );
  241. if( !res ){//semaphore got
  242. //check response
  243. if( this->passiveAuthModeIndicator == PA_SUCCESS ) foundFlag = 0xff;
  244. else if( this->passiveAuthModeIndicator != PA_FAILED ){
  245. printf( "[ipcd] FATAL ERROR: Passive auth return unexpected response: 0x%02x\n", this->passiveAuthModeIndicator );
  246. goto l_sendResult;
  247. }
  248. //disabling passive auth
  249. this->passiveAuthUsername = NULL;
  250. this->passiveAuthModeSwitcher = PA_STOP;
  251. this->passiveAuthModeIndicator = PA_STOP;
  252. sem_post( &this->semaphoreScan );
  253. } else {//socket drop or any error
  254. l_abort:
  255. //signal to idle mode to stop passive auth
  256. this->passiveAuthModeSwitcher = PA_STOP;
  257. sem_post( &this->semaphoreIdle );
  258. //wait for the stop response
  259. l_waitStopResponse:
  260. sem_wait( &this->semaphoreIpc );
  261. //if it is response with auth result
  262. if( this->passiveAuthModeIndicator != PA_STOP ){
  263. sem_post( &this->semaphoreScan );
  264. goto l_waitStopResponse;
  265. }
  266. //set username to NULL for disable passive auth
  267. this->passiveAuthUsername = NULL;
  268. sem_post( &this->semaphoreScan );
  269. }
  270. }
  271. l_sendResult:
  272. //send result
  273. if( write(socket, foundFlag ? &IPC_SUCCESS : &IPC_ERROR, 1) != 1 ) goto l_perror;
  274. goto l_exit;
  275. l_perror:
  276. perror( "[ipcd]" );
  277. l_exit:
  278. //restore previous mode
  279. driverSwitchMode( this, savedMode );
  280. }
  281. /*
  282. proto:
  283. <cmd>
  284. <id> <userlen> [user] <descriptionlen> [description]
  285. ...
  286. <0>
  287. */
  288. static void listFinger( int socket ){
  289. void* db;
  290. int id;
  291. int i;
  292. db = fingerdbOpen();
  293. if( !db ) return;
  294. //cmd
  295. if( write(socket, &IPC_FINGER_LIST, 1) != 1 ) goto l_perror;
  296. l_searchNext:
  297. id = fingerdbSearchNextId( db );
  298. if( !id ){
  299. //end of list
  300. id = 0;
  301. if( write(socket, &id, sizeof(id)) != sizeof(id) ) goto l_perror;
  302. goto l_closedb;
  303. }
  304. //send id
  305. if( write(socket, &id, sizeof(id)) != sizeof(id) ) goto l_perror;
  306. //send fields
  307. for( i = 0; i < 2; i++ ){
  308. if( printFieldContentToSocket(socket, id, &ipcFieldList[i]) ) goto l_closedb;
  309. }
  310. goto l_searchNext;
  311. l_perror:
  312. perror( "[ipcd]" );
  313. l_closedb:
  314. fingerdbClose( db );
  315. }
  316. /*
  317. request: IPC_FINGER_DETECT
  318. answer: IPC_FINGER_DETECT <id(int)> || IPC_ERROR
  319. also messages from driver
  320. */
  321. static void fingerDetect( struct driverInstance* this, int socket ){
  322. int res;
  323. unsigned char savedMode;
  324. savedMode = this->modeIndicator;
  325. //finger scan
  326. res = getFingerImageFromScanner( this, socket );
  327. if( res == -ECONNRESET ) goto l_exit;
  328. //search matches
  329. if( !res ) res = authSearchMatch( this->data, NULL );
  330. //send result
  331. if( res < 0 ){
  332. if( write(socket, &IPC_ERROR, 1 ) != 1 ) goto l_perror;
  333. } else {
  334. if( write(socket, &IPC_FINGER_DETECT, 1 ) != 1 ) goto l_perror;
  335. if( write(socket, &res, sizeof(res)) != sizeof(res) ) goto l_perror;
  336. }
  337. goto l_exit;
  338. l_perror:
  339. perror( "[ipcd]" );
  340. l_exit:
  341. driverSwitchMode( this, savedMode );
  342. }
  343. /********************
  344. * ADMIN *
  345. ********************/
  346. /*
  347. request: <IPC_FINGER_ADD> <MODE>
  348. answer
  349. <IPC_FINGER_ADD> <int>
  350. <IPC_SUCCESS> <ID>
  351. <IPC_ERROR>
  352. also messages from driver
  353. */
  354. static void newFinger( struct driverInstance* this, int socket ){
  355. int res;
  356. unsigned char addMode;
  357. unsigned char savedMode;
  358. int attempts;
  359. int* currentXytCount;
  360. struct xyt_packed* currentXyt;
  361. int xyt1Count;
  362. int xyt2Count;
  363. struct xyt_packed xyt1[NBIS_XYT_MAX_COUNT];
  364. struct xyt_packed xyt2[NBIS_XYT_MAX_COUNT];
  365. savedMode = this->modeIndicator;
  366. //read mode
  367. if( recv(socket, &addMode, 1, MSG_WAITALL) != 1 ){
  368. perror( "[ipcd]" );
  369. return;
  370. }
  371. //check socket security
  372. if( checkSocketSecurity(socket) ){
  373. if( write(socket, &IPC_DENIED, 1) != 1 ) perror( "[ipcd]" );
  374. return;
  375. }
  376. //check mode
  377. if( addMode != IPC_FINGER_ADD_SINGLE && addMode != IPC_FINGER_ADD_BEST ){
  378. printf( "[ipcd] Unknown new finger add mode: 0x%02x\n", addMode );
  379. if( write(socket, &IPC_ERROR, 1) != 1 ) perror( "[ipcd]" );
  380. return;
  381. }
  382. //init some vars
  383. xyt1Count = 0;
  384. xyt2Count = 0;
  385. attempts = 0;
  386. currentXyt = xyt1;
  387. currentXytCount = &xyt1Count;
  388. l_scanAgain:
  389. //scan finger
  390. res = getFingerImageFromScanner( this, socket );
  391. if( res == -ECONNRESET ) goto l_exit;
  392. if( res ) goto l_sendError;
  393. //get minutiae on fingerprint
  394. *currentXytCount = nbisPgmToMinutiae( this->data, currentXyt );
  395. if( *currentXytCount < 0 ) goto l_sendError;
  396. //notify client about scan result
  397. if( write(socket, &IPC_FINGER_ADD, 1 ) != 1 ) goto l_perror;
  398. if( write(socket, currentXytCount, sizeof(*currentXytCount)) != sizeof(*currentXytCount) ) goto l_perror;
  399. if( addMode == IPC_FINGER_ADD_SINGLE ) goto l_register;
  400. //switch to minimal
  401. if( currentXyt == xyt1 ){
  402. if( xyt1Count > xyt2Count ){
  403. attempts = 0;
  404. currentXyt = xyt2;
  405. currentXytCount = &xyt2Count;
  406. }
  407. }else{
  408. if( xyt2Count > xyt1Count ){
  409. attempts = 0;
  410. currentXyt = xyt1;
  411. currentXytCount = &xyt1Count;
  412. }
  413. }
  414. //check attempts count
  415. if( attempts < 3 ){
  416. attempts++;
  417. goto l_scanAgain;
  418. }
  419. //select best fingerprint
  420. if( currentXyt == xyt1 ){
  421. currentXyt = xyt2;
  422. currentXytCount = &xyt2Count;
  423. }else{
  424. currentXyt = xyt1;
  425. currentXytCount = &xyt1Count;
  426. }
  427. l_register:
  428. //create new record in finger DB
  429. res = authEnroll( currentXyt, *currentXytCount );
  430. //send result
  431. if( res < 0 ){
  432. l_sendError:
  433. if( write(socket, &IPC_ERROR, 1 ) != 1 ) goto l_perror;
  434. } else {
  435. if( write(socket, &IPC_SUCCESS, 1 ) != 1 ) goto l_perror;
  436. if( write(socket, &res, sizeof(res)) != sizeof(res) ) goto l_perror;
  437. }
  438. goto l_exit;
  439. l_perror:
  440. perror( "[ipcd]" );
  441. l_exit:
  442. driverSwitchMode( this, savedMode );
  443. }
  444. /*
  445. proto
  446. <IPC_SUCCESS> or <IPC_ERROR>
  447. <len> [data] user
  448. <len> [data] desc
  449. <len> [data] threshold
  450. <len> [data] action
  451. */
  452. static void viewFinger( int socket ){
  453. int i;
  454. int id;
  455. //read id
  456. if( recv(socket, &id, sizeof(id), MSG_WAITALL) != sizeof(id) ) goto l_perror;
  457. //check socket security
  458. if( checkSocketSecurity(socket) ){
  459. if( write(socket, &IPC_DENIED, 1) != 1 ) goto l_perror;
  460. return;
  461. }
  462. //check id exist
  463. if( !fingerdbCheckIdExist(id) ){
  464. if( write(socket, &IPC_ERROR, 1) != 1 ) goto l_perror;
  465. return;
  466. }
  467. if( write(socket, &IPC_SUCCESS, 1) != 1 ) goto l_perror;
  468. //read content in fields and send it
  469. for( i = 0; i < 4; i++ ){
  470. if( printFieldContentToSocket(socket, id, &ipcFieldList[i]) ) return;
  471. }
  472. return;
  473. l_perror:
  474. perror( "[icd]" );
  475. }
  476. /*
  477. request: <IPC_FINGER_EDIT> <ID> <FIELD ID> <LENGTH> [NEW VALUE]
  478. answer: <IPC_SUCCESS> || <IPC_ERROR>
  479. */
  480. static void editFinger( int socket ){
  481. int i;
  482. int res;
  483. int id;
  484. unsigned char fieldId;
  485. int len;
  486. char buf[1024];
  487. int value;
  488. const struct ipc_field* field = NULL;
  489. //receive id, fieldid, len and new value
  490. if( recv(socket, &id, sizeof(id), MSG_WAITALL) != sizeof(id) ) goto l_perror;
  491. if( recv(socket, &fieldId, 1, MSG_WAITALL) != 1 ) goto l_perror;
  492. if( recv(socket, &len, sizeof(len), MSG_WAITALL) != sizeof(len) ) goto l_perror;
  493. if( len > 1023 || len < 0 ){//check len
  494. res = -1;
  495. goto l_sendAnswer;
  496. }
  497. if( len ){
  498. if( recv(socket, buf, len, MSG_WAITALL) != len ) goto l_perror;
  499. }
  500. buf[len] = 0x00; //string must be null-terminated
  501. //check socket security
  502. if( checkSocketSecurity(socket) ){
  503. if( write(socket, &IPC_DENIED, 1) != 1 ) goto l_perror;
  504. return;
  505. }
  506. //check requested field
  507. for( i = 0; ipcFieldList[i].name; i++ ) if( ipcFieldList[i].id == fieldId ){
  508. field = &ipcFieldList[i];
  509. goto l_found;
  510. }
  511. printf( "%s) WARNING! Wrong field requested: 0x%02x\n", __FUNCTION__, fieldId );
  512. res = -1;
  513. goto l_sendAnswer;
  514. l_found:
  515. //convert text to int if need
  516. if( field->type == 'i' ){
  517. //if len == 0, then clear field
  518. if( !len ) goto l_setAsText;
  519. if( sscanf(buf, "%i", &value) != 1 ){
  520. res = -1;
  521. goto l_sendAnswer;
  522. }
  523. //set value as int
  524. res = fingerdbSetField( id, field->name, &value, sizeof(value) );
  525. }else if( field->type == 't' ){
  526. l_setAsText: //set new value as text
  527. res = fingerdbSetField( id, field->name, buf, len );
  528. } else {
  529. printf( "%s) WARNING: unknow field type: %c\n", __FUNCTION__, field->type );
  530. res = -1;
  531. }
  532. l_sendAnswer: //send answer
  533. if( write(socket, res ? &IPC_ERROR : &IPC_SUCCESS, 1) != 1 ) goto l_perror;
  534. return;
  535. l_perror:
  536. perror( "[ipcd]" );
  537. }
  538. /*
  539. request <IPC_FINGER_TEST> <id>
  540. response: <IPC_FINGER_TEST> <score> || <IPC_ERROR>
  541. also messages from driver
  542. */
  543. static void testFinger( struct driverInstance* this, int socket ){
  544. int id;
  545. int res;
  546. unsigned char savedMode;
  547. savedMode = this->modeIndicator;
  548. //read id
  549. if( recv(socket, &id, sizeof(id), MSG_WAITALL) != sizeof(id) ) goto l_perror;
  550. //check socket security
  551. if( checkSocketSecurity(socket) ){
  552. if( write(socket, &IPC_DENIED, 1) != 1 ) perror( "[ipcd]" );
  553. return;
  554. }
  555. //check id exist
  556. if( !fingerdbCheckIdExist(id) ){
  557. if( write(socket, &id, sizeof(id)) != sizeof(id) ) goto l_perror;
  558. return;
  559. }
  560. //scan finger and calculate match score
  561. res = getFingerImageFromScanner( this, socket );
  562. if( !res ) res = authTest( id, this->data );
  563. //send result
  564. if( res < 0 ){
  565. if( write(socket, &IPC_ERROR, 1) != 1 ) perror( "[ipcd]" );
  566. } else {
  567. if( write(socket, &IPC_FINGER_TEST, 1) != 1 ) perror( "[ipcd]" );
  568. else if( write(socket, &res, sizeof(res)) != sizeof(res) ) perror( "[ipcd]" );
  569. }
  570. driverSwitchMode( this, savedMode );
  571. return;
  572. l_perror:
  573. perror( "[ipcd]" );
  574. }
  575. /*
  576. request: <IPC_FINGER_REMOVE> <ID>
  577. answer: <IPC_SUCCESS> or <IPC_FAILED>
  578. */
  579. static void removeFinger( int socket ){
  580. int id;
  581. //read id
  582. if( recv(socket, &id, sizeof(id), MSG_WAITALL) != sizeof(id) ) goto l_perror;
  583. //check socket security
  584. if( checkSocketSecurity(socket) ){
  585. if( write(socket, &IPC_DENIED, 1) != 1 ) perror( "[ipcd]" );
  586. return;
  587. }
  588. //remove record from DB ande send result
  589. if( !fingerdbRemoveFinger(id) ){
  590. if( write(socket, &IPC_SUCCESS, 1) != 1 ) goto l_perror;
  591. }else {
  592. if( write(socket, &IPC_ERROR, 1) != 1 ) goto l_perror;
  593. }
  594. return;
  595. l_perror:
  596. perror( "[ipcd]" );
  597. }
  598. /***************************
  599. * HANDLER SWITCHER *
  600. ***************************/
  601. static void connectionHandler( struct driverInstance* this, int socket ){
  602. unsigned char cmd;
  603. l_recvCmd:
  604. //read command from socket
  605. if ( recv(socket, &cmd, 1, MSG_WAITALL) != 1 ) return;
  606. //user cmd
  607. if( cmd == IPC_TOUCHPAD ) touchpadControl( this, socket );
  608. else if( cmd == IPC_USER_AUTH ) authUser( this, socket );
  609. else if( cmd == IPC_FINGER_LIST ) listFinger( socket );
  610. else if( cmd == IPC_FINGER_DETECT ) fingerDetect( this, socket );
  611. //admin cmd
  612. else if( cmd == IPC_FINGER_ADD ) newFinger( this, socket );
  613. else if( cmd == IPC_FINGER_VIEW ) viewFinger( socket );
  614. else if( cmd == IPC_FINGER_EDIT ) editFinger( socket );
  615. else if( cmd == IPC_FINGER_TEST ) testFinger( this, socket );
  616. else if( cmd == IPC_FINGER_REMOVE ) removeFinger( socket );
  617. else{
  618. printf( "[ipcd] Received unknown ipc command: 0x%02x\n", cmd );
  619. if( write(socket, &IPC_ERROR, 1) != 1 ){//unknown command
  620. perror( "[ipcd] (unk cmd)" );
  621. return;
  622. }
  623. }
  624. goto l_recvCmd;
  625. }
  626. /*************************
  627. * IPCD ENTRY POINT *
  628. *************************/
  629. void* ipcdEntryPoint( void* arg ){
  630. struct driverInstance* this = arg;
  631. int mySocket;
  632. int clientSocket;
  633. struct sockaddr_un socketAddress;
  634. prctl( PR_SET_NAME, "ipcd", 0, 0, 0 );
  635. //Create local socket.
  636. mySocket = socket( AF_UNIX, SOCK_STREAM, 0 );
  637. if( mySocket == -1 ) {
  638. printf( "[ipcd] Unable create socket %s\n", IPC_SOCKET );
  639. return NULL;
  640. }
  641. memset( &socketAddress, 0, sizeof(struct sockaddr_un) );
  642. // Bind socket to socket name.
  643. socketAddress.sun_family = AF_UNIX;
  644. strncpy( socketAddress.sun_path, IPC_SOCKET, sizeof(socketAddress.sun_path) - 1 );
  645. if( bind(mySocket, (const struct sockaddr*) &socketAddress, sizeof(struct sockaddr_un)) ){
  646. perror( "[ipcd] bind" );
  647. return NULL;
  648. }
  649. //Prepare for accepting connections.
  650. if( listen(mySocket, 5) ){
  651. perror( "[ipcd] listen" );
  652. return NULL;
  653. }
  654. //This is the main loop for handling connections.
  655. for(;;) {
  656. //Wait for incoming connection.
  657. clientSocket = accept( mySocket, NULL, NULL );
  658. if( clientSocket == -1 ) {
  659. perror( "[ipcd] accept" );
  660. break;
  661. }
  662. //handle command
  663. connectionHandler( this, clientSocket );
  664. //Close socket.
  665. close( clientSocket );
  666. }
  667. close( mySocket );
  668. return NULL;
  669. }