mirror of
https://github.com/openbsd/src.git
synced 2025-01-03 06:45:37 -08:00
Add a set of flags to rmt(8) to make it run in a restricted mode,
designed to work with rdump(8) to remote disk. -d <directory> confines rmt to operate within a single directory. -r enforces read-only mode. -w enforces write-only mode. This is quite usable with public ssh key setup, e.g. having the following in .ssh/authorized/keys: command="/etc/rmt -rd /backups/machine.example.conf",no-agent-forwarding,... ssh-rsa AAAAB3... ok semarie@
This commit is contained in:
parent
e9abc84819
commit
71c04358ef
@ -1,4 +1,4 @@
|
||||
.\" $OpenBSD: rmt.8,v 1.12 2011/07/23 15:40:13 schwarze Exp $
|
||||
.\" $OpenBSD: rmt.8,v 1.13 2015/09/20 10:05:48 halex Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1983, 1991 The Regents of the University of California.
|
||||
.\" All rights reserved.
|
||||
@ -29,19 +29,22 @@
|
||||
.\"
|
||||
.\" from: @(#)rmt.8 6.5 (Berkeley) 3/16/91
|
||||
.\"
|
||||
.Dd $Mdocdate: July 23 2011 $
|
||||
.Dd $Mdocdate: September 20 2015 $
|
||||
.Dt RMT 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm rmt
|
||||
.Nd remote magtape protocol module
|
||||
.Sh SYNOPSIS
|
||||
.Nm rmt
|
||||
.Nm
|
||||
.Op Fl r | w
|
||||
.Op Fl d Ar directory
|
||||
.Sh DESCRIPTION
|
||||
.Nm
|
||||
is a program used by the remote dump and restore programs
|
||||
in manipulating a magnetic tape drive through an interprocess
|
||||
communication connection.
|
||||
through an interprocess communication connection.
|
||||
Traditionally it is used for manipulating a magnetic tape drive but it may
|
||||
be used for regular file access as well.
|
||||
.Nm
|
||||
is normally started up with an
|
||||
.Xr rcmd 3
|
||||
@ -49,6 +52,23 @@ or
|
||||
.Xr rcmdsh 3
|
||||
call.
|
||||
.Pp
|
||||
The options are as follows:
|
||||
.Bl -tag -width Ds
|
||||
.It Fl d Ar directory
|
||||
Confine file access to
|
||||
.Ar directory .
|
||||
Forward slashes in filenames are disallowed and symlinks are not followed.
|
||||
.It Fl r
|
||||
Read-only mode, suitable for use with
|
||||
.Xr rrestore 8 .
|
||||
.It Fl w
|
||||
File write mode, suitable for use with
|
||||
.Xr rdump 8
|
||||
for dumping to regular files.
|
||||
Creates missing files and refuses to open existing ones.
|
||||
The file permission bits are set to readonly.
|
||||
.El
|
||||
.Pp
|
||||
The
|
||||
.Nm
|
||||
program accepts requests specific to the manipulation of
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: rmt.c,v 1.15 2015/01/16 06:40:20 deraadt Exp $ */
|
||||
/* $OpenBSD: rmt.c,v 1.16 2015/09/20 10:05:48 halex Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1983 Regents of the University of California.
|
||||
@ -41,6 +41,7 @@
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
@ -52,6 +53,7 @@ int maxrecsize = -1;
|
||||
|
||||
#define STRSIZE 64
|
||||
char device[PATH_MAX];
|
||||
char lastdevice[PATH_MAX] = "";
|
||||
char count[STRSIZE], mode[STRSIZE], pos[STRSIZE], op[STRSIZE];
|
||||
|
||||
char resp[BUFSIZ];
|
||||
@ -61,9 +63,10 @@ FILE *debug;
|
||||
#define DEBUG1(f,a) if (debug) fprintf(debug, f, a)
|
||||
#define DEBUG2(f,a1,a2) if (debug) fprintf(debug, f, a1, a2)
|
||||
|
||||
char *checkbuf(char *, int);
|
||||
void getstring(char *, int);
|
||||
void error(int);
|
||||
char *checkbuf(char *, int);
|
||||
void getstring(char *, int);
|
||||
void error(int);
|
||||
__dead void usage(void);
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
@ -72,14 +75,50 @@ main(int argc, char *argv[])
|
||||
int rval;
|
||||
char c;
|
||||
int n, i, cc;
|
||||
int ch, rflag = 0, wflag = 0;
|
||||
int f, acc;
|
||||
mode_t m;
|
||||
char *dir = NULL;
|
||||
char *devp;
|
||||
size_t dirlen;
|
||||
|
||||
while ((ch = getopt(argc, argv, "d:rw")) != -1) {
|
||||
switch (ch) {
|
||||
case 'd':
|
||||
dir = optarg;
|
||||
if (*dir != '/')
|
||||
errx(1, "directory must be absolute");
|
||||
break;
|
||||
case 'r':
|
||||
rflag = 1;
|
||||
break;
|
||||
case 'w':
|
||||
wflag = 1;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
/* NOTREACHED */
|
||||
}
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (rflag && wflag)
|
||||
usage();
|
||||
|
||||
argc--, argv++;
|
||||
if (argc > 0) {
|
||||
debug = fopen(*argv, "w");
|
||||
if (debug == 0)
|
||||
exit(1);
|
||||
err(1, "cannot open debug file");
|
||||
(void) setbuf(debug, (char *)0);
|
||||
}
|
||||
|
||||
if (dir) {
|
||||
if (chdir(dir) != 0)
|
||||
err(1, "chdir");
|
||||
dirlen = strlen(dir);
|
||||
}
|
||||
|
||||
top:
|
||||
errno = 0;
|
||||
rval = 0;
|
||||
@ -93,10 +132,66 @@ top:
|
||||
getstring(device, sizeof(device));
|
||||
getstring(mode, sizeof(mode));
|
||||
DEBUG2("rmtd: O %s %s\n", device, mode);
|
||||
tape = open(device, atoi(mode),
|
||||
S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
|
||||
|
||||
devp = device;
|
||||
f = atoi(mode);
|
||||
m = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH;
|
||||
acc = f & O_ACCMODE;
|
||||
if (dir) {
|
||||
/* Strip away valid directory prefix. */
|
||||
if (strncmp(dir, devp, dirlen) == 0 &&
|
||||
(devp[dirlen - 1] == '/' ||
|
||||
devp[dirlen] == '/')) {
|
||||
devp += dirlen;
|
||||
while (*devp == '/')
|
||||
devp++;
|
||||
}
|
||||
/* Don't allow directory traversal. */
|
||||
if (strchr(devp, '/')) {
|
||||
errno = EACCES;
|
||||
goto ioerror;
|
||||
}
|
||||
f |= O_NOFOLLOW;
|
||||
}
|
||||
if (rflag) {
|
||||
/*
|
||||
* Only allow readonly open and ignore file
|
||||
* creation requests.
|
||||
*/
|
||||
if (acc != O_RDONLY) {
|
||||
errno = EPERM;
|
||||
goto ioerror;
|
||||
}
|
||||
f &= ~O_CREAT;
|
||||
} else if (wflag) {
|
||||
/*
|
||||
* Require, and force creation of, a nonexistant file,
|
||||
* unless we are reopening the last opened file again,
|
||||
* in which case it is opened read-only.
|
||||
*/
|
||||
if (strcmp(devp, lastdevice) != 0) {
|
||||
/*
|
||||
* Disallow read-only open since that would
|
||||
* only result in an empty file.
|
||||
*/
|
||||
if (acc == O_RDONLY) {
|
||||
errno = EPERM;
|
||||
goto ioerror;
|
||||
}
|
||||
f |= O_CREAT | O_EXCL;
|
||||
} else {
|
||||
acc = O_RDONLY;
|
||||
}
|
||||
/* Create readonly file */
|
||||
m = S_IRUSR|S_IRGRP|S_IROTH;
|
||||
}
|
||||
/* Apply new access mode. */
|
||||
f = (f & ~O_ACCMODE) | acc;
|
||||
|
||||
tape = open(devp, f, m);
|
||||
if (tape == -1)
|
||||
goto ioerror;
|
||||
(void)strlcpy(lastdevice, devp, sizeof(lastdevice));
|
||||
goto respond;
|
||||
|
||||
case 'C':
|
||||
@ -225,3 +320,13 @@ error(int num)
|
||||
(void) snprintf(resp, sizeof (resp), "E%d\n%s\n", num, strerror(num));
|
||||
(void) write(STDOUT_FILENO, resp, strlen(resp));
|
||||
}
|
||||
|
||||
__dead void
|
||||
usage(void)
|
||||
{
|
||||
extern char *__progname;
|
||||
|
||||
(void)fprintf(stderr, "usage: %s [-r | -w] [-d directory]\n",
|
||||
__progname);
|
||||
exit(1);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user