PageRenderTime 57ms CodeModel.GetById 25ms RepoModel.GetById 1ms app.codeStats 0ms

/zuluCrypt-cli/bin/add_key.c

https://gitlab.com/m.schmidt/zuluCrypt
C | 381 lines | 246 code | 52 blank | 83 comment | 43 complexity | 86b0e7e2b5f076b1a2ba3b3c05b73961 MD5 | raw file
Possible License(s): BSD-3-Clause-No-Nuclear-License-2014, BSD-2-Clause
  1. /*
  2. *
  3. * Copyright (c) 2011-2015
  4. * name : Francis Banyikwa
  5. * email: mhogomchungu@gmail.com
  6. * This program is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include "includes.h"
  20. #include "../lib/includes.h"
  21. #include <locale.h>
  22. #include <stdio.h>
  23. #include <libintl.h>
  24. #include <sys/stat.h>
  25. typedef struct{
  26. const char * device ;
  27. const char * existing_key ;
  28. size_t existing_key_size ;
  29. size_t existing_key_is_keyfile ;
  30. const char * new_key ;
  31. size_t new_key_size ;
  32. size_t new_key_is_keyfile ;
  33. }tcrypt_opts ;
  34. /*
  35. * Its not possible to add more keys to a volume with no empty slots or to a non luks volume
  36. *
  37. * This function checks if a volume is luks and if it has atleast one empty slot.
  38. */
  39. static int _zuluCryptCheckEmptySlots( const char * device )
  40. {
  41. int r = 0 ;
  42. char * c ;
  43. char * d ;
  44. zuluCryptSecurityGainElevatedPrivileges() ;
  45. /*
  46. * zuluCryptVolumeIsLuks() is defined in ../lib/is_luks.c
  47. */
  48. if( zuluCryptVolumeIsLuks( device ) ){
  49. /*
  50. * zuluCryptEmptySlots() is defined in ../lib/empty_slots.c
  51. */
  52. c = zuluCryptEmptySlots( device ) ;
  53. if( c == NULL ){
  54. /*
  55. * we shouldnt get here
  56. */
  57. r = 1 ;
  58. }else{
  59. d = c - 1 ;
  60. while( *++d ){
  61. if( *d == '0' ){
  62. r = 2 ;
  63. break ;
  64. }
  65. }
  66. StringFree( c ) ;
  67. }
  68. }else{
  69. /*
  70. * volume is not a LUKS volume,assuming its a TrueCrypt volume
  71. */
  72. r = 2 ;
  73. }
  74. zuluCryptSecurityDropElevatedPrivileges() ;
  75. return r ;
  76. }
  77. static int _replace_truecrypt_key( const tcrypt_opts * opts )
  78. {
  79. info_t info ;
  80. string_t st = StringVoid ;
  81. string_t xt = StringVoid ;
  82. int r ;
  83. memset( &info,'\0',sizeof( info_t ) ) ;
  84. info.device = opts->device ;
  85. /*
  86. * zuluCryptCreateKeyFile() is defined in ../lib/open_tcrypt.c
  87. */
  88. if( opts->existing_key_is_keyfile ){
  89. info.header_key_source = "keyfiles" ;
  90. st = zuluCryptCreateKeyFile( opts->existing_key,opts->existing_key_size,"add-tcrypt-1" ) ;
  91. info.header_key = StringContent( st ) ;
  92. }else{
  93. info.header_key_source = "passphrase" ;
  94. info.header_key = opts->existing_key ;
  95. }
  96. if( opts->new_key_is_keyfile ){
  97. info.header_new_key_source = "new_keyfiles" ;
  98. st = zuluCryptCreateKeyFile( opts->new_key,opts->new_key_size,"add-tcrypt-2" ) ;
  99. info.header_new_key = StringContent( st ) ;
  100. }else{
  101. info.header_new_key_source = "new_passphrase" ;
  102. info.header_new_key = opts->new_key ;
  103. }
  104. info.rng = "/dev/urandom" ;
  105. /*
  106. * zuluCryptModifyTcryptHeader() is defined in ../lib/create_tcrypt.c
  107. */
  108. r = zuluCryptModifyTcryptHeader( &info ) ;
  109. /*
  110. * zuluCryptDeleteFile_1() is defined in ../lib/file_path_security.c
  111. */
  112. if( st != StringVoid ){
  113. zuluCryptDeleteFile_1( st ) ;
  114. StringDelete( &st ) ;
  115. }
  116. if( xt != StringVoid ){
  117. zuluCryptDeleteFile_1( xt ) ;
  118. StringDelete( &xt ) ;
  119. }
  120. if( r == 0 ){
  121. return 0 ;
  122. }else{
  123. return 1 ;
  124. }
  125. }
  126. static int zuluExit( int st,stringList_t stl )
  127. {
  128. zuluCryptSecurityUnlockMemory( stl ) ;
  129. /*
  130. * this function is defined in ../string/StringList.c
  131. */
  132. StringListClearDelete( &stl ) ;
  133. switch( st ){
  134. case 0 : printf( gettext( "SUCCESS: key added successfully\n" ) ) ; break ;
  135. case 1 : printf( gettext( "ERROR: Presented key does not match any key in the volume\n" ) ) ; break ;
  136. case 2 : printf( gettext( "ERROR: Could not open luks volume\n" ) ) ; break ;
  137. case 3 : printf( gettext( "ERROR: Volume is not a luks volume\n" ) ); break ;
  138. case 4 : printf( gettext( "ERROR: Insufficient privilege to open a system device,\n\
  139. only root user or members of group \"zulucrypt\" can do that\n" ) ) ; break ;
  140. case 5 : printf( gettext( "ERROR: Could not open volume in write mode\n" ) ) ; break ;
  141. case 6 : printf( gettext( "ERROR: All key slots are occupied, can not add any more keys\n" ) ) ; break ;
  142. case 7 : printf( gettext( "ERROR: Can not get passphrase in silent mode\n" ) ) ; break ;
  143. case 8 : printf( gettext( "ERROR: Insufficient memory to hold passphrase\n" ) ) ; break ;
  144. case 9 : printf( gettext( "ERROR: New passphrases do not match\n" ) ) ; break ;
  145. case 10 : printf( gettext( "ERROR: One or more required argument(s) for this operation is missing\n" ));break ;
  146. case 11 : printf( gettext( "ERROR: One or both keyfile(s) does not exist\n" ) ) ; break ;
  147. case 12 : printf( gettext( "ERROR: Insufficient privilege to open key file for reading\n" ) ) ; break ;
  148. case 13 : printf( gettext( "ERROR: Couldnt get enought memory to hold the key file\n" ) ) ; break ;
  149. case 14 : printf( gettext( "ERROR: Could not get a key from a socket\n" ) ) ; break ;
  150. case 15 : printf( gettext( "ERROR: Could not get elevated privilege,check binary permissions\n" ) ) ; break ;
  151. default : printf( gettext( "ERROR: Unrecognized error with status number %d encountered\n" ),st ) ;
  152. }
  153. return st ;
  154. }
  155. static int zuluGetKeys( string_t * key1,string_t * key2,string_t * key3 )
  156. {
  157. int st ;
  158. /*
  159. * ZULUCRYPT_KEY_MAX_SIZE is set in ../constants.h
  160. */
  161. printf( gettext( "Enter an existing passphrase: " ) ) ;
  162. st = StringSilentlyGetFromTerminal_1( key1,ZULUCRYPT_KEY_MAX_SIZE ) ;
  163. if( st != 0 ){
  164. return st ;
  165. }
  166. printf( gettext( "\nEnter the new passphrase: " ) ) ;
  167. st = StringSilentlyGetFromTerminal_1( key2,ZULUCRYPT_KEY_MAX_SIZE ) ;
  168. if( st != 0 ){
  169. StringClearDelete( key1 ) ;
  170. return st ;
  171. }
  172. printf( gettext( "\nRe enter the new passphrase: " ) ) ;
  173. st = StringSilentlyGetFromTerminal_1( key3,ZULUCRYPT_KEY_MAX_SIZE ) ;
  174. if( st != 0 ){
  175. StringClearDelete( key1 ) ;
  176. StringClearDelete( key2 ) ;
  177. return st ;
  178. }
  179. printf( "\n" ) ;
  180. return 0 ;
  181. }
  182. /*
  183. * get_pass_from_file function is defined at get_pass_from_file.c *
  184. */
  185. int zuluCryptEXEAddKey( const struct_opts * opts,uid_t uid )
  186. {
  187. const char * device = opts->device ;
  188. const char * keyType1 = opts->existing_key_source ;
  189. const char * existingKey = opts->existing_key ;
  190. const char * keyType2 = opts->new_key_source ;
  191. const char * newKey = opts->new_key ;
  192. /*
  193. * Below is a form of memory management.All strings are collected in a stringlist object to easily delete them
  194. * when the function returns.This allows for the function to have multiple exit points without risks of leaking
  195. * memory from manually examining each exit point to make sure all strings are deleted or go with multiple goto
  196. * code deleting blocks to take into account different exit points.
  197. */
  198. stringList_t stl ;
  199. string_t * stringArray = StringListArray( &stl,5 ) ;
  200. string_t * presentKey = &stringArray[ 0 ] ;
  201. string_t * newKey_1 = &stringArray[ 1 ] ;
  202. string_t * newKey_2 = &stringArray[ 2 ] ;
  203. string_t * ek = &stringArray[ 3 ] ;
  204. string_t * nk = &stringArray[ 4 ] ;
  205. const char * key1 = NULL ;
  206. const char * key2 = NULL ;
  207. size_t len1 = 0 ;
  208. size_t len2 = 0 ;
  209. int status = 0 ;
  210. tcrypt_opts tcrypt ;
  211. memset( &tcrypt,'\0',sizeof( tcrypt_opts ) ) ;
  212. /*
  213. * zuluCryptPartitionIsSystemPartition() is defined in ./partitions.c
  214. */
  215. if( zuluCryptPartitionIsSystemPartition( device,uid ) ){
  216. if( !zuluCryptUserIsAMemberOfAGroup( uid,"zulucrypt" ) ){
  217. return zuluExit( 4,stl ) ;
  218. }
  219. }
  220. /*
  221. * zuluCryptSecurityDeviceIsWritable() is defined in path_access.c
  222. */
  223. status = zuluCryptCanOpenPathForWriting( device,uid ) ;
  224. /*
  225. * 1-permissions denied
  226. * 2-invalid path
  227. * 3-shenanigans
  228. * 4-common error
  229. */
  230. switch( status ){
  231. case 0 : break ;
  232. case 1 : return zuluExit( 5,stl ) ;
  233. case 2 : return zuluExit( 5,stl ) ;
  234. case 3 : return zuluExit( 5,stl ) ;
  235. case 4 : return zuluExit( 5,stl ) ;
  236. default: return zuluExit( 5,stl ) ;
  237. }
  238. switch( _zuluCryptCheckEmptySlots( device ) ){
  239. case 0 : return zuluExit( 6,stl ) ;
  240. case 1 : return zuluExit( 2,stl ) ;
  241. case 2 : /* no complains,continue */ ;
  242. }
  243. if( keyType1 == NULL && keyType2 == NULL ){
  244. switch( zuluGetKeys( presentKey,newKey_1,newKey_2 ) ){
  245. case 1 : return zuluExit( 7,stl ) ;
  246. case 2 : return zuluExit( 8,stl ) ;
  247. }
  248. if( StringEqualString( *newKey_1,*newKey_2 ) ){
  249. key1 = StringContent( *presentKey ) ;
  250. len1 = StringLength ( *presentKey ) ;
  251. key2 = StringContent( *newKey_1 ) ;
  252. len2 = StringLength ( *newKey_1 ) ;
  253. }else{
  254. return zuluExit( 9,stl ) ;
  255. }
  256. }else{
  257. if( newKey == NULL || existingKey == NULL ){
  258. return zuluExit( 10,stl ) ;
  259. }
  260. if( StringsAreEqual( keyType1,"-f" ) ){
  261. /*
  262. * this function is defined at "path_access.c"
  263. */
  264. switch( zuluCryptGetPassFromFile( existingKey,uid,ek ) ){
  265. case 1 : return zuluExit( 11,stl ) ;
  266. case 4 : return zuluExit( 12,stl ) ;
  267. case 2 : return zuluExit( 13,stl ) ;
  268. case 5 : return zuluExit( 14,stl ) ;
  269. }
  270. key1 = StringContent( *ek ) ;
  271. len1 = StringLength( *ek ) ;
  272. if( StringHasNoComponent( existingKey,"/.zuluCrypt-socket" ) ){
  273. tcrypt.existing_key_is_keyfile = 1 ;
  274. }
  275. }
  276. if( StringsAreEqual( keyType2,"-f" ) ){
  277. /*
  278. * this function is defined at "path_access.c"
  279. */
  280. switch( zuluCryptGetPassFromFile( newKey,uid,nk ) ){
  281. case 1 : return zuluExit( 11,stl ) ;
  282. case 4 : return zuluExit( 12,stl ) ;
  283. case 2 : return zuluExit( 13,stl ) ;
  284. case 5 : return zuluExit( 14,stl ) ;
  285. }
  286. key2 = StringContent( *nk ) ;
  287. len2 = StringLength( *nk ) ;
  288. if( StringHasNoComponent( newKey,"/.zuluCrypt-socket" ) ){
  289. tcrypt.new_key_is_keyfile = 1 ;
  290. }
  291. }
  292. if( StringsAreEqual( keyType1,"-f" ) && StringsAreEqual( keyType2,"-f" ) ){
  293. ;
  294. }else if( StringsAreEqual( keyType1,"-p" ) && StringsAreEqual( keyType2,"-p" ) ){
  295. key1 = existingKey ;
  296. len1 = StringSize( existingKey ) ;
  297. key2 = newKey ;
  298. len2 = StringSize( newKey ) ;
  299. }else if( StringsAreEqual( keyType1,"-p" ) && StringsAreEqual( keyType2,"-f" ) ){
  300. key1 = existingKey ;
  301. len1 = StringSize( existingKey ) ;
  302. }else if( StringsAreEqual( keyType1,"-f" ) && StringsAreEqual( keyType2,"-p" ) ){
  303. key2 = newKey ;
  304. len2 = StringSize( newKey ) ;
  305. }else{
  306. return zuluExit( 10,stl ) ;
  307. }
  308. }
  309. zuluCryptSecurityLockMemory( stl ) ;
  310. zuluCryptSecurityGainElevatedPrivileges() ;
  311. /*
  312. * zuluCryptVolumeIsLuks() is defined in ../lib/is_luks.c
  313. */
  314. if( zuluCryptVolumeIsLuks( device ) ){
  315. /*
  316. * zuluCryptAddKey() is defined in ../lib/add_key.c
  317. */
  318. status = zuluCryptAddKey( device,key1,len1,key2,len2 ) ;
  319. }else{
  320. tcrypt.device = device ;
  321. tcrypt.existing_key = key1 ;
  322. tcrypt.existing_key_size = len1 ;
  323. tcrypt.new_key = key2 ;
  324. tcrypt.new_key_size = len2 ;
  325. status = _replace_truecrypt_key( &tcrypt ) ;
  326. }
  327. zuluCryptSecurityDropElevatedPrivileges() ;
  328. return zuluExit( status,stl ) ;
  329. }