MCPcopy Index your code
hub / github.com/ether/etherpad / _update

Method _update

src/node/security/SecretRotator.ts:168–261  ·  view source on GitHub ↗
()

Source from the content-addressed store, hash-verified

166 }
167
168 async _update() {
169 const now = this._t.now();
170 const t0 = intervalStart(now, this._interval);
171 let next = t0 + this._interval; // When this._update() should be called again.
172 let legacyEnd = now;
173 // TODO: This is racy. If two instances start up at the same time and there are no existing
174 // matching publications, each will generate and publish their own paramters. In practice this
175 // is unlikely to happen, and if it does it can be fixed by restarting both Etherpad instances.
176 const dbKeys:string[] = await db.findKeys(`${this._dbPrefix}:*`, null) || [];
177 let currentParams:any = null;
178 let currentId = null;
179 const dbWrites:any[] = [];
180 const allParams = [];
181 const legacyParams:LegacyParams[] = [];
182 await Promise.all(dbKeys.map(async (dbKey) => {
183 const p = await db.get(dbKey);
184 if (p.algId === 0 && p.algParams === this._legacyStaticSecret) legacyParams.push(p);
185 if (p.start < legacyEnd) legacyEnd = p.start;
186 // Check if the params have expired. Params are still useful if a MAC generated by a secret
187 // derived from the params is still valid, which can be true up to p.end + p.lifetime if
188 // there was no clock skew. The p.interval factor is added to accommodate clock skew.
189 // p.interval is null for legacy secrets, so fall back to this._interval.
190 if (now >= p.end + p.lifetime + (p.interval || this._interval)) {
191 // This initial keying material (or legacy secret) is expired.
192 dbWrites.push(db.remove(dbKey));
193 dbWrites[dbWrites.length - 1].catch(() => {}); // Prevent unhandled Promise rejections.
194 return;
195 }
196 const t1 = p.interval && intervalStart(now, p.interval) + p.interval; // Start of next intrvl.
197 const tA = intervalStart(p.start, p.interval); // Start of interval containing p.start.
198 if (p.interval) next = Math.min(next, t1);
199 // Determine if these params can be used to generate the current (active) secret. Note that
200 // p.start is allowed to be in the next interval in case there is clock skew.
201 if (p.interval && p.interval === this._interval && p.lifetime === this._lifetime &&
202 tA <= t1 && p.end > now && (currentParams == null || p.start > currentParams.start)) {
203 if (currentParams) allParams.push(currentParams);
204 currentParams = p;
205 currentId = dbKey;
206 } else {
207 allParams.push(p);
208 }
209 }));
210 if (this._legacyStaticSecret && now < legacyEnd + this._lifetime + this._interval &&
211 !legacyParams.find((p) => p.end + p.lifetime >= legacyEnd + this._lifetime)) {
212 const d = new Date(legacyEnd).toJSON();
213 this._logger.debug(`adding legacy static secret for ${d} with lifetime ${this._lifetime}`);
214 const p: LegacyParams = {
215 algId: 0,
216 algParams: this._legacyStaticSecret,
217 // The start time is equal to the end time so that this legacy secret does not affect the
218 // end times of any legacy secrets published by other instances.
219 start: legacyEnd,
220 end: legacyEnd,
221 interval: null,
222 lifetime: this._lifetime,
223 };
224 allParams.push(p);
225 dbWrites.push(this._publish(p));

Callers 1

startMethod · 0.95

Calls 12

_publishMethod · 0.95
_deriveSecretsMethod · 0.95
nowMethod · 0.80
mapMethod · 0.80
getMethod · 0.80
pushMethod · 0.80
findMethod · 0.80
setTimeoutMethod · 0.80
intervalStartFunction · 0.70
removeMethod · 0.45
toJSONMethod · 0.45
generateParamsMethod · 0.45

Tested by

no test coverage detected