zulip_tools: Replace deprecated mktemp call.

Although mktemp is deprecated due to security issues, this is not a
security issue.

The security problems with mktemp happen when you open the resulting
filename (without O_EXCL) in a publicly writable directory, because
then someone else might have predicted the filename and created or
symlinked or hardlinked something there between the mktemp and the
open, causing you to write to a file you didn’t expect.

Here we don’t open the resulting filename, we symlink to it.  symlink
will refuse to clobber an existing file, and we handle the error that
arises from this case.  This is the normal way to atomically create a
symlink.

We should still replace mktemp because it’s deprecated, but we can’t
replace it with a function that creates the temporary file.  Instead
we build a random filename ourselves.

Signed-off-by: Anders Kaseorg <anders@zulip.com>
This commit is contained in:
Anders Kaseorg 2020-07-09 11:31:34 -07:00 committed by Tim Abbott
parent 0b4568d249
commit ff1622afcf
1 changed files with 6 additions and 4 deletions

View File

@ -8,12 +8,12 @@ import json
import logging
import os
import pwd
import random
import re
import shlex
import shutil
import subprocess
import sys
import tempfile
import time
import uuid
from typing import Any, Dict, List, Sequence, Set
@ -40,10 +40,12 @@ MAGENTA = '\x1b[35m'
CYAN = '\x1b[36m'
def overwrite_symlink(src: str, dst: str) -> None:
dir, base = os.path.split(dst)
while True:
tmp = tempfile.mktemp(
prefix='.' + os.path.basename(dst) + '.',
dir=os.path.dirname(dst))
# Note: creating a temporary filename like this is not generally
# secure. Its fine in this case because os.symlink refuses to
# overwrite an existing target; we handle the error and try again.
tmp = os.path.join(dir, ".{}.{:010x}".format(base, random.randrange(1 << 40)))
try:
os.symlink(src, tmp)
except FileExistsError: