17
17
-include_lib (" kernel/include/file.hrl" ).
18
18
-endif .
19
19
20
- -export ([start_link /2 , start_link /3 , extract_hidden_pass /0 ,
20
+ -export ([start_link /3 , start_link /4 , extract_hidden_pass /0 ,
21
21
extract_hidden_pass /1 , stop /0 ]).
22
22
-export ([init /1 , handle_call /3 , handle_cast /2 ,
23
23
handle_info /2 , terminate /2 , code_change /3 ]).
@@ -147,17 +147,17 @@ remove_old_integrity_tokens(Name, Paths) ->
147
147
get_key_id_in_use (Name ) ->
148
148
gen_server :call (Name , get_key_id_in_use , infinity ).
149
149
150
- start_link (Logger , PasswordPromptAllowed ) ->
151
- start_link (Logger , PasswordPromptAllowed , gosecrets_cfg_path ()).
150
+ start_link (Logger , PasswordPromptAllowed , ReadOnly ) ->
151
+ start_link (Logger , PasswordPromptAllowed , ReadOnly , gosecrets_cfg_path ()).
152
152
153
- start_link (Logger , PasswordPromptAllowed , ConfigPath ) ->
153
+ start_link (Logger , PasswordPromptAllowed , ReadOnly , ConfigPath ) ->
154
154
gen_server :start_link ({local , ? MODULE }, ? MODULE ,
155
- [ConfigPath , Logger , PasswordPromptAllowed ], []).
155
+ [ConfigPath , Logger , PasswordPromptAllowed , ReadOnly ], []).
156
156
157
157
stop () ->
158
158
gen_server :call (? MODULE , stop , infinity ).
159
159
160
- prompt_the_password (State , Retries ) ->
160
+ prompt_the_password (State , Retries , ReadOnly ) ->
161
161
StdIn =
162
162
case application :get_env (handle_ctrl_c ) of
163
163
{ok , true } ->
@@ -166,7 +166,7 @@ prompt_the_password(State, Retries) ->
166
166
undefined
167
167
end ,
168
168
try
169
- prompt_the_password (State , Retries , StdIn )
169
+ prompt_the_password (State , Retries , ReadOnly , StdIn )
170
170
after
171
171
case StdIn of
172
172
undefined ->
@@ -176,12 +176,12 @@ prompt_the_password(State, Retries) ->
176
176
end
177
177
end .
178
178
179
- prompt_the_password (State , MaxRetries , StdIn ) ->
179
+ prompt_the_password (State , MaxRetries , ReadOnly , StdIn ) ->
180
180
case open_udp_socket (State ) of
181
181
{ok , Socket } ->
182
182
try
183
183
save_port_file (Socket ),
184
- prompt_the_password (State , MaxRetries , StdIn ,
184
+ prompt_the_password (State , MaxRetries , ReadOnly , StdIn ,
185
185
Socket , _RetriesLeft = MaxRetries )
186
186
after
187
187
file :delete (port_file_path ()),
@@ -191,7 +191,7 @@ prompt_the_password(State, MaxRetries, StdIn) ->
191
191
{error , {udp_socket_open_failed , Error }}
192
192
end .
193
193
194
- prompt_the_password (State , MaxRetries , StdIn , Socket , RetriesLeft ) ->
194
+ prompt_the_password (State , MaxRetries , ReadOnly , StdIn , Socket , RetriesLeft ) ->
195
195
{ok , {Addr , Port }} = inet :sockname (Socket ),
196
196
log (info , " Waiting for the master password to be supplied (UDP: ~p :~b ). "
197
197
" Attempt ~p (~p attempts left)" ,
@@ -201,7 +201,7 @@ prompt_the_password(State, MaxRetries, StdIn, Socket, RetriesLeft) ->
201
201
log (error , " Password prompt interrupted: ~p " , [M ], State ),
202
202
{error , interrupted };
203
203
{udp , Socket , FromAddr , FromPort , Password } ->
204
- case call_init (? HIDE (Password ), State ) of
204
+ case call_init (? HIDE (Password ), ReadOnly , State ) of
205
205
ok ->
206
206
gen_udp :send (Socket , FromAddr , FromPort , <<" ok" >>),
207
207
ok ;
@@ -210,7 +210,7 @@ prompt_the_password(State, MaxRetries, StdIn, Socket, RetriesLeft) ->
210
210
State ),
211
211
gen_udp :send (Socket , FromAddr , FromPort , <<" retry" >>),
212
212
timer :sleep (1000 ),
213
- prompt_the_password (State , MaxRetries , StdIn ,
213
+ prompt_the_password (State , MaxRetries , ReadOnly , StdIn ,
214
214
Socket , RetriesLeft - 1 );
215
215
{Reply , _Reason } when Reply == error ;
216
216
Reply == wrong_password ->
@@ -219,7 +219,7 @@ prompt_the_password(State, MaxRetries, StdIn, Socket, RetriesLeft) ->
219
219
end
220
220
end .
221
221
222
- init ([GosecretsCfgPath , Logger , PasswordPromptAllowed ]) ->
222
+ init ([GosecretsCfgPath , Logger , PasswordPromptAllowed , ReadOnly ]) ->
223
223
State = # state {config = GosecretsCfgPath ,
224
224
logger = Logger },
225
225
@@ -235,7 +235,7 @@ init([GosecretsCfgPath, Logger, PasswordPromptAllowed]) ->
235
235
HiddenPass = extract_hidden_pass (),
236
236
237
237
init_gosecrets (HiddenPass , _MaxRetries = 3 , PasswordPromptAllowed ,
238
- NewState ),
238
+ ReadOnly , NewState ),
239
239
240
240
{ok , NewState }.
241
241
@@ -250,14 +250,15 @@ save_config(CfgPath, Cfg, State) ->
250
250
erlang :error ({write_failed , CfgPath , Error })
251
251
end .
252
252
253
- init_gosecrets (HiddenPass , MaxRetries , PasswordPromptAllowed , State ) ->
254
- case call_init (HiddenPass , State ) of
253
+ init_gosecrets (HiddenPass , MaxRetries , PasswordPromptAllowed , ReadOnly ,
254
+ State ) ->
255
+ case call_init (HiddenPass , ReadOnly , State ) of
255
256
ok -> ok ;
256
257
{wrong_password , ErrorMsg } ->
257
258
case PasswordPromptAllowed and should_prompt_the_password (State ) of
258
259
true ->
259
260
try
260
- case prompt_the_password (State , MaxRetries ) of
261
+ case prompt_the_password (State , MaxRetries , ReadOnly ) of
261
262
ok ->
262
263
ok ;
263
264
{error , Error } ->
@@ -284,8 +285,8 @@ init_gosecrets(HiddenPass, MaxRetries, PasswordPromptAllowed, State) ->
284
285
erlang :error ({gosecrets_init_failed , Error })
285
286
end .
286
287
287
- call_init (HiddenPass , State ) ->
288
- case call_gosecrets ({init , HiddenPass }, State ) of
288
+ call_init (HiddenPass , ReadOnly , State ) ->
289
+ case call_gosecrets ({init , ReadOnly , HiddenPass }, State ) of
289
290
ok ->
290
291
memorize_hidden_pass (HiddenPass ),
291
292
log (info , " Init complete. Password (if used) accepted." , [], State ),
@@ -465,7 +466,7 @@ gosecret_do_process_exit(Port, {'EXIT', Port, Reason}) ->
465
466
gosecret_do_process_exit (_Port , {'EXIT' , _ , Reason }) ->
466
467
exit (Reason ).
467
468
468
- encode ({init , HiddenPass }) ->
469
+ encode ({init_read_only , HiddenPass }) ->
469
470
BinaryPassword = encode_password (HiddenPass ),
470
471
<<1 , BinaryPassword /binary >>;
471
472
encode (get_keys_ref ) ->
@@ -518,7 +519,15 @@ encode({remove_old_integrity_tokens, Paths}) ->
518
519
PathsBin = list_to_binary ([encode_param (P ) || P <- Paths ]),
519
520
<<18 , PathsBin /binary >>;
520
521
encode (get_key_id_in_use ) ->
521
- <<19 >>.
522
+ <<19 >>;
523
+ encode ({init , IsReadOnly , HiddenPass }) ->
524
+ BinaryPassword = encode_password (HiddenPass ),
525
+ ReadOnlyBin = case IsReadOnly of
526
+ true -> <<1 >>;
527
+ false -> <<0 >>
528
+ end ,
529
+ <<20 , (encode_param (ReadOnlyBin ))/binary ,
530
+ (encode_param (BinaryPassword ))/binary >>.
522
531
523
532
encode_param (B ) when is_atom (B ) ->
524
533
encode_param (atom_to_binary (B ));
@@ -1157,7 +1166,7 @@ upgrade_from_7_2_no_password_test() ->
1157
1166
undefined ,
1158
1167
fun (CfgPath ) ->
1159
1168
ok = file :write_file (DKeyPath , base64 :decode (DKeyNoPass )),
1160
- {ok , Pid } = start_link (default , true , CfgPath ),
1169
+ {ok , Pid } = start_link (default , true , true , CfgPath ),
1161
1170
try
1162
1171
Data = rand :bytes (512 ),
1163
1172
{ok , Encrypted } = encrypt (Pid , Data ),
@@ -1186,7 +1195,7 @@ upgrade_from_7_2_with_password_test() ->
1186
1195
undefined ,
1187
1196
fun (CfgPath ) ->
1188
1197
ok = file :write_file (DKeyPath , base64 :decode (DKeyNoPass )),
1189
- {ok , Pid } = start_link (default , true , CfgPath ),
1198
+ {ok , Pid } = start_link (default , true , true , CfgPath ),
1190
1199
try
1191
1200
Data = rand :bytes (512 ),
1192
1201
{ok , Encrypted } = encrypt (Pid , Data ),
@@ -1396,7 +1405,7 @@ with_gosecrets(Cfg, Fun, ResetMemorizePassword) ->
1396
1405
with_tmp_cfg (
1397
1406
Cfg ,
1398
1407
fun (CfgPath ) ->
1399
- {ok , Pid } = start_link (default , true , CfgPath ),
1408
+ {ok , Pid } = start_link (default , true , false , CfgPath ),
1400
1409
try
1401
1410
Fun (CfgPath , Pid )
1402
1411
after
0 commit comments