Skip to content

Commit 70e5060

Browse files
committed
Add support for managing registration lock
1 parent 10db88a commit 70e5060

File tree

4 files changed

+111
-69
lines changed

4 files changed

+111
-69
lines changed

libsignal-service-dotnet/SignalServiceAccountManager.cs

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,14 @@ public SignalServiceAccountManager(SignalServiceConfiguration configuration, Can
6161
PushServiceSocket = new PushServiceSocket(configuration, new StaticCredentialsProvider(null, null, null, (int)SignalServiceAddress.DEFAULT_DEVICE_ID), userAgent);
6262
}
6363

64+
public void SetPin(string pin)
65+
{
66+
if (pin != null)
67+
PushServiceSocket.SetPin(pin);
68+
else
69+
PushServiceSocket.RemovePin();
70+
}
71+
6472
/// <summary>
6573
/// Register/Unregister a Google Cloud Messaging registration ID.
6674
/// </summary>
@@ -111,10 +119,10 @@ public void RequestVoiceVerificationCode()// throws IOException
111119
/// <param name="fetchesMessages">True if the client does not support GCM</param>
112120
/// <returns></returns>
113121
public void VerifyAccountWithCode(string verificationCode, string signalingKey,
114-
uint signalProtocolRegistrationId, bool fetchesMessages)
122+
uint signalProtocolRegistrationId, bool fetchesMessages, string pin)
115123
{
116124
this.PushServiceSocket.VerifyAccountCode(verificationCode, signalingKey,
117-
signalProtocolRegistrationId, fetchesMessages);
125+
signalProtocolRegistrationId, fetchesMessages, pin);
118126
}
119127

120128
/// <summary>
@@ -127,9 +135,9 @@ public void VerifyAccountWithCode(string verificationCode, string signalingKey,
127135
/// separate installs.</param>
128136
/// <param name="fetchesMessages">True if the client does not support GCM</param>
129137
/// <returns></returns>
130-
public void SetAccountAttributes(string signalingKey, uint signalProtocolRegistrationId, bool fetchesMessages)
138+
public void SetAccountAttributes(string signalingKey, uint signalProtocolRegistrationId, bool fetchesMessages, string pin)
131139
{
132-
this.PushServiceSocket.SetAccountAttributes(signalingKey, signalProtocolRegistrationId, fetchesMessages);
140+
this.PushServiceSocket.SetAccountAttributes(signalingKey, signalProtocolRegistrationId, fetchesMessages, pin);
133141
}
134142

135143
/// <summary>
@@ -210,15 +218,6 @@ public List<ContactTokenDetails> GetContacts(IList<string> e164numbers)
210218
return activeTokens;
211219
}
212220

213-
/// <summary>
214-
/// Soon to be deprecated
215-
/// </summary>
216-
/// <returns></returns>
217-
public string GetAccountVerificationToken()
218-
{
219-
return PushServiceSocket.GetAccountVerificationToken();
220-
}
221-
222221
/// <summary>
223222
/// Request a UUID from the server for linking as a new device.
224223
/// Called by the new device.

libsignal-service-dotnet/push/AccountAttributes.cs

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,27 +23,31 @@ namespace libsignalservice.push
2323
internal class AccountAttributes
2424
{
2525
[JsonProperty("signalingKey", Required = Required.Always)]
26-
private string SignalingKey { get; set; }
26+
private string SignalingKey { get; }
2727

2828
[JsonProperty("registrationId", Required = Required.Always)]
29-
private uint RegistrationId { get; set; }
29+
private uint RegistrationId { get; }
3030

3131
[JsonProperty("voice", Required = Required.Always)]
32-
private bool Voice { get; set; }
32+
private bool Voice { get; }
3333

3434
[JsonProperty("video", Required = Required.Always)]
35-
private bool Video { get; set; }
35+
private bool Video { get; }
3636

3737
[JsonProperty("fetchesMessages", Required = Required.Always)]
38-
private bool FetchesMessages { get; set; }
38+
private bool FetchesMessages { get; }
39+
40+
[JsonProperty("pin")]
41+
private string Pin { get; }
3942

40-
public AccountAttributes(string signalingKey, uint registrationId, bool fetchesMessages)
43+
public AccountAttributes(string signalingKey, uint registrationId, bool fetchesMessages, string pin)
4144
{
4245
SignalingKey = signalingKey;
4346
RegistrationId = registrationId;
4447
Voice = true;
4548
Video = true;
46-
FetchesMessages = fetchesMessages;
49+
FetchesMessages = fetchesMessages;
50+
Pin = pin;
4751
}
4852
}
4953
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Text;
4+
5+
namespace libsignalservice.push
6+
{
7+
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
8+
public class LockedException : Exception
9+
{
10+
public int Length { get; }
11+
public long TimeRemaining { get; }
12+
13+
public LockedException(int length, long timeRemaining)
14+
{
15+
Length = length;
16+
TimeRemaining = timeRemaining;
17+
}
18+
}
19+
#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member
20+
}

libsignal-service-dotnet/push/PushServiceSocket.cs

Lines changed: 68 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,11 @@ internal class PushServiceSocket
3636
private static readonly string CREATE_ACCOUNT_SMS_PATH = "/v1/accounts/sms/code/{0}";
3737
private static readonly string CREATE_ACCOUNT_VOICE_PATH = "/v1/accounts/voice/code/{0}";
3838
private static readonly string VERIFY_ACCOUNT_CODE_PATH = "/v1/accounts/code/{0}";
39-
private static readonly string VERIFY_ACCOUNT_TOKEN_PATH = "/v1/accounts/token/{0}";
4039
private static readonly string REGISTER_GCM_PATH = "/v1/accounts/gcm/";
4140
private static readonly string REQUEST_TOKEN_PATH = "/v1/accounts/token";
4241
private static readonly string TURN_SERVER_INFO = "/v1/accounts/turn";
4342
private static readonly string SET_ACCOUNT_ATTRIBUTES = "/v1/accounts/attributes";
43+
private static readonly String PIN_PATH = "/v1/accounts/pin/";
4444

4545
private static readonly string PREKEY_METADATA_PATH = "/v2/keys/";
4646
private static readonly string PREKEY_PATH = "/v2/keys/{0}";
@@ -77,26 +77,20 @@ public bool CreateAccount(bool voice)
7777
return true;
7878
}
7979

80-
public bool VerifyAccountCode(string verificationCode, string signalingKey, uint registrationId, bool fetchesMessages)
80+
public bool VerifyAccountCode(string verificationCode, string signalingKey, uint registrationId, bool fetchesMessages, string pin)
8181
{
82-
AccountAttributes signalingKeyEntity = new AccountAttributes(signalingKey, registrationId, fetchesMessages);
82+
AccountAttributes signalingKeyEntity = new AccountAttributes(signalingKey, registrationId, fetchesMessages, pin);
8383
MakeServiceRequest(string.Format(VERIFY_ACCOUNT_CODE_PATH, verificationCode), "PUT", JsonUtil.toJson(signalingKeyEntity));
8484
return true;
8585
}
8686

87-
public bool SetAccountAttributes(string signalingKey, uint registrationId, bool fetchesMessages)
87+
public bool SetAccountAttributes(string signalingKey, uint registrationId, bool fetchesMessages, string pin)
8888
{
89-
AccountAttributes accountAttributesEntity = new AccountAttributes(signalingKey, registrationId, fetchesMessages);
89+
AccountAttributes accountAttributesEntity = new AccountAttributes(signalingKey, registrationId, fetchesMessages, pin);
9090
MakeServiceRequest(SET_ACCOUNT_ATTRIBUTES, "PUT", JsonUtil.toJson(accountAttributesEntity));
9191
return true;
9292
}
9393

94-
public string GetAccountVerificationToken()// throws IOException
95-
{
96-
string responseText = MakeServiceRequest(REQUEST_TOKEN_PATH, "GET", null);
97-
return JsonUtil.fromJson<AuthorizationToken>(responseText).Token;
98-
}
99-
10094
public int FinishNewDeviceRegistration(String code, String signalingKey, bool supportsSms, bool fetchesMessages, int registrationId, String deviceName)
10195
{
10296
ConfirmCodeMessage javaJson = new ConfirmCodeMessage(signalingKey, supportsSms, fetchesMessages, registrationId, deviceName);
@@ -142,6 +136,17 @@ public void UnregisterGcmId()
142136
MakeServiceRequest(REGISTER_GCM_PATH, "DELETE", null);
143137
}
144138

139+
public void SetPin(string pin)
140+
{
141+
RegistrationLock accountLock = new RegistrationLock(pin);
142+
MakeServiceRequest(PIN_PATH, "PUT", JsonUtil.toJson(accountLock));
143+
}
144+
145+
public void RemovePin()
146+
{
147+
MakeServiceRequest(PIN_PATH, "PUT", null);
148+
}
149+
145150
public SendMessageResponse SendMessage(OutgoingPushMessageList bundle)
146151
{
147152
try
@@ -350,13 +355,13 @@ public bool SetCurrentSignedPreKey(SignedPreKeyRecord signedPreKey)// throws IOE
350355
string response = MakeServiceRequest(string.Format(ATTACHMENT_PATH, ""), "GET", null);
351356
AttachmentDescriptor attachmentKey = JsonUtil.fromJson<AttachmentDescriptor>(response);
352357

353-
if (attachmentKey == null || attachmentKey.getLocation() == null)
358+
if (attachmentKey == null || attachmentKey.Location == null)
354359
{
355360
throw new Exception("Server failed to allocate an attachment key!");
356361
}
357362

358-
Debug.WriteLine("Got attachment content location: " + attachmentKey.getLocation(), TAG);
359-
return (attachmentKey.getId(), attachmentKey.getLocation());
363+
Debug.WriteLine("Got attachment content location: " + attachmentKey.Location, TAG);
364+
return (attachmentKey.Id, attachmentKey.Location);
360365
}
361366

362367
public void RetrieveAttachment(string relay, ulong attachmentId, Stream tmpDestination, int maxSizeBytes)
@@ -383,8 +388,8 @@ public string RetrieveAttachmentDownloadUrl(string relay, ulong attachmentId)
383388
string response = MakeServiceRequest(path, "GET", null);
384389
Debug.WriteLine("PushServiceSocket: Received resp " + response);
385390
AttachmentDescriptor descriptor = JsonUtil.fromJson<AttachmentDescriptor>(response);
386-
Debug.WriteLine("PushServiceSocket: Attachment: " + attachmentId + " is at: " + descriptor.getLocation());
387-
return descriptor.getLocation();
391+
Debug.WriteLine("PushServiceSocket: Attachment: " + attachmentId + " is at: " + descriptor.Location);
392+
return descriptor.Location;
388393
}
389394

390395
public SignalServiceProfile RetrieveProfile(SignalServiceAddress target)
@@ -627,16 +632,16 @@ private string MakeServiceRequest(string urlFragment, string method, string body
627632
throw new PushNetworkException(ioe);
628633
}
629634

630-
switch (responseCode)
635+
switch ((uint)responseCode)
631636
{
632-
case HttpStatusCode.RequestEntityTooLarge: // 413
637+
case 413: // HttpStatusCode.RequestEntityTooLarge
633638
throw new RateLimitException("Rate limit exceeded: " + responseCode);
634-
case HttpStatusCode.Unauthorized: // 401
635-
case HttpStatusCode.Forbidden: // 403
639+
case 401: // HttpStatusCode.Unauthorized
640+
case 403: // HttpStatusCode.Forbidden
636641
throw new AuthorizationFailedException("Authorization failed!");
637-
case HttpStatusCode.NotFound: // 404
642+
case 404: // HttpStatusCode.NotFound
638643
throw new NotFoundException("Not found");
639-
case HttpStatusCode.Conflict: // 409
644+
case 409: // HttpStatusCode.Conflict
640645
MismatchedDevices mismatchedDevices = null;
641646
try
642647
{
@@ -649,7 +654,7 @@ private string MakeServiceRequest(string urlFragment, string method, string body
649654
throw new PushNetworkException(e);
650655
}
651656
throw new MismatchedDevicesException(mismatchedDevices);
652-
case HttpStatusCode.Gone: // 410
657+
case 410: // HttpStatusCode.Gone
653658
StaleDevices staleDevices = null;
654659
try
655660
{
@@ -662,21 +667,30 @@ private string MakeServiceRequest(string urlFragment, string method, string body
662667
throw new PushNetworkException(e);
663668
}
664669
throw new StaleDevicesException(staleDevices);
665-
case HttpStatusCode.LengthRequired://411:
670+
case 411: //HttpStatusCode.LengthRequired
666671
DeviceLimit deviceLimit = null;
667672
try
668673
{
669674
deviceLimit = JsonUtil.fromJson<DeviceLimit>(responseBody);
670675
}
671676
catch (Exception e)
672677
{
673-
Debug.WriteLine(e);
674-
Debug.WriteLine(e.StackTrace);
675678
throw new PushNetworkException(e);
676679
}
677680
throw new DeviceLimitExceededException(deviceLimit);
678-
case HttpStatusCode.ExpectationFailed: // 417
681+
case 417: // HttpStatusCode.ExpectationFailed
679682
throw new ExpectationFailedException();
683+
case 423:
684+
RegistrationLockFailure accountLockFailure;
685+
try
686+
{
687+
accountLockFailure = JsonUtil.fromJson<RegistrationLockFailure>(responseBody);
688+
}
689+
catch (Exception e)
690+
{
691+
throw new PushNetworkException(e);
692+
}
693+
throw new LockedException(accountLockFailure.Length, accountLockFailure.TimeRemaining);
680694
}
681695

682696
if (responseCode != HttpStatusCode.OK && responseCode != HttpStatusCode.NoContent) // 200 & 204
@@ -780,39 +794,44 @@ private SignalUrl GetRandom(SignalUrl[] connections)
780794

781795
internal class GcmRegistrationId
782796
{
783-
[JsonProperty]
784-
private string wnsRegistrationId;
797+
[JsonProperty("wnsRegistrationId")]
798+
public string WnsRegistrationId { get; }
785799

786-
[JsonProperty]
787-
private bool webSocketChannel;
788-
789-
public GcmRegistrationId()
790-
{
791-
}
800+
[JsonProperty("webSocketChannel")]
801+
public bool WebSocketChannel { get; }
792802

793803
public GcmRegistrationId(string wnsRegistrationId, bool webSocketChannel)
794804
{
795-
this.wnsRegistrationId = wnsRegistrationId;
796-
this.webSocketChannel = webSocketChannel;
805+
WnsRegistrationId = wnsRegistrationId;
806+
WebSocketChannel = webSocketChannel;
797807
}
798808
}
799809

800-
internal class AttachmentDescriptor
810+
internal class RegistrationLock
801811
{
802-
[JsonProperty]
803-
private ulong id;
812+
[JsonProperty("pin")]
813+
public string Pin { get; }
804814

805-
[JsonProperty]
806-
private string location;
807-
808-
public ulong getId()
815+
public RegistrationLock(string pin)
809816
{
810-
return id;
817+
Pin = pin;
811818
}
819+
}
812820

813-
public string getLocation()
814-
{
815-
return location;
816-
}
821+
internal class RegistrationLockFailure
822+
{
823+
[JsonProperty("length")]
824+
public int Length { get; }
825+
[JsonProperty("timeRemaining")]
826+
public long TimeRemaining { get; }
827+
}
828+
829+
internal class AttachmentDescriptor
830+
{
831+
[JsonProperty("id")]
832+
public ulong Id { get; }
833+
834+
[JsonProperty("location")]
835+
public string Location { get; }
817836
}
818837
}

0 commit comments

Comments
 (0)