scram.c revision d67944fbe3fa0b31893a7116a09b0718eecf6078
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
#include <curses.h>
#define _SYS_TERMIO_H /* sys/termio.h is included by curses.h */
#include <fcntl.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include "wish.h"
#include "vtdefs.h"
#include "token.h"
#include "obj.h"
#include "typetab.h"
#include "partabdefs.h"
#include "parse.h"
#include "retcds.h"
#include "exception.h"
#include "terror.h"
#include "winp.h"
#include "moremacros.h"
#include "sizes.h"
#define KEYSIZE 101
extern char *Home;
static unsigned char Keycheck[KEYSIZE];
static char Passwd[20];
static char Keyprompt[35];
static char Srcfile[PATHSIZ];
static int cryptit(), mkencrypart();
static char scram_string[] = "scramble";
static char uscram_string[] = "unscramble";
static int check_key();
static int crypt_file();
static int pack();
static int unpack();
static int keysave();
static int keyvalid();
static void regetkey();
/*
* scram -- Scramble an object and pack all its parts into an OEU package
*/
int
scram(file)
register char *file;
{
strcpy(Keyprompt, "Please enter scramble key: ");
strcpy(Srcfile, file);
get_string(regetkey, Keyprompt, "",
I_INVISIBLE, FALSE, scram_string, scram_string);
return (0);
}
/*
* unscram -- Unscramble an object which was packed into an OEU package before
*/
int
unscram(file)
register char *file;
{
int keysave();
strcpy(Keyprompt, "Please enter unscramble key: ");
strcpy(Srcfile, file);
get_string(keysave, Keyprompt, "",
I_INVISIBLE, FALSE, uscram_string, uscram_string);
return (0);
}
static void
regetkey(s, t)
char *s;
token t;
{
int keyvalid();
if (t == TOK_CANCEL)
return;
strcpy(Passwd, s);
get_string(keyvalid, "Please re-enter scramble key: ", "",
I_INVISIBLE, FALSE, scram_string, scram_string);
}
static int
keyvalid(s, t)
char *s;
token t;
{
struct ott_entry *entry, *path_to_ott();
struct stat buf;
if (t == TOK_CANCEL)
return (SUCCESS);
if (strcmp(Passwd, s) != 0) {
mess_temp("The two scramble keys are different.");
get_string(regetkey, Keyprompt, "",
I_INVISIBLE, FALSE, scram_string, scram_string);
return (SUCCESS);
} else {
stat(Srcfile, &buf); /* return code check? */
if ((entry = path_to_ott(Srcfile)) == NULL)
return (FAIL);
working(TRUE);
if (mkencrypart() == FAIL ||
crypt_file(entry, buf, FALSE) == FAIL ||
pack(entry, buf) == FAIL)
return (FAIL);
else {
ott_mark(entry, M_EN, TRUE);
return (SUCCESS);
}
}
}
static int
keysave(s, t)
char *s;
token t;
{
struct ott_entry *entry, *path_to_ott();
char package[PATHSIZ];
struct stat buf;
int check_key();
strcpy(Passwd, s);
stat(Srcfile, &buf); /* return code check? */
if ((entry = path_to_ott(Srcfile)) == NULL)
return (FAIL);
working(TRUE);
strcpy(package, Home);
strcat(package, "/tmp/.TMPorigin");
if (unpack(entry, package) == FAIL) {
unlink(package);
return (FAIL);
}
if (check_key(entry) == SUCCESS) {
crypt_file(entry, buf, TRUE);
unlink(package);
ott_mark(entry, M_EN, FALSE);
} else {
(void) pack(entry, buf);
unlink(Srcfile);
if (movefile(package, Srcfile))
unlink(package);
/* get_string(keysave, Keyprompt, "", */
/* I_INVISIBLE, FALSE, scram_string, scram_string); */
}
return (SUCCESS);
}
static int
unpack(entry, package)
struct ott_entry *entry;
char *package;
{
struct opt_entry *part_ent, *obj_to_opt();
struct one_part *opt_next_part();
char *filename(), *nameptr;
char path[PATHSIZ], action[(PATHSIZ * 2) + 20];
char *part_match();
FILE *pipeptr, *popen();
part_ent = obj_to_opt(entry->objtype);
if (!part_ent) {
warn(MUNGED, NULL);
return (FAIL);
}
nameptr = part_match(filename(Srcfile),
opt_next_part(part_ent)->part_template);
movefile(Srcfile, package);
sprintf(path, "%s/%s", entry->dirpath, nameptr);
sprintf(action, "oeupkg -u -d %s -s %s", path, package);
if ((pipeptr = popen(action, "r")) == NULL)
fatal(NOPEN, action);
/* abs:added cast */
if (fgets((char *)Keycheck, KEYSIZE, pipeptr) == NULL)
return (FAIL);
Keycheck[KEYSIZE - 1] = 0; /* ?? */
pclose(pipeptr);
return (SUCCESS);
}
static int
pack(entry, buf)
struct ott_entry *entry;
struct stat buf;
{
char temp[PATHSIZ];
char action[(PATHSIZ * 3) + 80];
struct ott_entry *ptr, *ott_next_part(), *name_to_ott();
strcpy(temp, Home);
strcat(temp, "/tmp/.TMPscram");
sprintf(action, "oeupkg -d %s -s %s -o %s -e %s",
temp, Srcfile, entry->objtype, Keycheck);
if (waitspawn(sysspawn(action)) != R_OK)
return (FAIL);
if (chmod(temp, buf.st_mode) == 0 &&
chown(temp, buf.st_uid, buf.st_gid) == 0) {
unlink(Srcfile);
movefile(temp, Srcfile);
}
/* remove OTHER parts after packing */
ptr = ott_next_part(entry);
while (ptr) {
unlink(ott_to_path(ptr));
ott_mark(name_to_ott(ptr->name), M_DL, TRUE);
ptr = ott_next_part(ptr);
}
/* dereference children from parent */
ptr = name_to_ott(entry->name);
ptr->next_part = OTTNIL;
return (SUCCESS);
}
/*
* crypt_file -- encrypt or decrypt using the UNIX "crypt" command
*/
static int
crypt_file(entry, buf, create_entry)
struct ott_entry *entry;
struct stat buf;
int create_entry;
{
int i;
char action[PATHSIZ + 40], temp[PATHSIZ];
char path[PATHSIZ];
char *part, *base;
struct opt_entry *partab;
struct ott_entry *orig_entry;
extern struct one_part Parts[MAXPARTS];
char *part_match(), *part_construct();
struct opt_entry *obj_to_parts();
struct ott_entry *ott_make_entry(), *name_to_ott();
/* if either return NULL */
if (!(partab = obj_to_parts(entry->objtype)) ||
!(base = part_match(entry->name,
Parts[partab->part_offset].part_template)))
return (FAIL);
for (i = 0, part = base; i < partab->numparts; i++,
part = part_construct(base,
Parts[partab->part_offset+i].part_template)) {
sprintf(path, "%s/%s", entry->dirpath, part);
if (access(path, 0))
continue;
strcpy(temp, Home);
strcat(temp, "/tmp/.TMPcrypt");
(void) close(open(temp, O_EXCL | O_CREAT | O_TRUNC, 0600));
sprintf(action, "crypt '%s' < '%s' > '%s'", Passwd, path, temp);
if (waitspawn(sysspawn(action)) != 0) {
mess_temp("Encryption software not available");
return (FAIL);
}
if (chmod(temp, buf.st_mode) == 0 &&
chown(temp, buf.st_uid, buf.st_gid) == 0) {
unlink(path);
link(temp, path);
}
unlink(temp);
/* if need to create an entry (unscrambling) */
if (create_entry) {
/* since calling other routines */
part = strsave(part);
#ifdef _DEBUG
_debug(stderr, "creating entry for %s\n", part);
#endif
if ((i == 0) && (partab->numparts > 1)) {
/* remake parent so can do children - IF children exist */
orig_entry = name_to_ott(entry->name);
orig_entry->objmask |= M_DL;
entry = ott_make_entry(part,
entry->dname, entry->objtype,
entry->objmask, entry->odi, entry->mtime);
/* dupped entry so don't need to & out ~M_DL */
} else if (i != 0) /* add child */
ott_make_entry(part, NULL, NULL,
entry->objmask|partab->int_class,
NULL, entry->mtime);
free(part);
/* NOTE: part has been freed if anything is added after this */
}
}
if (create_entry && (partab->numparts > 1))
ott_synch(FALSE);
return (SUCCESS);
}
static int
check_key(entry)
struct ott_entry *entry;
{
int m, n;
unsigned char buf[51];
int left, right;
char tempstr[3];
tempstr[2] = '\0';
for (m = 0; m < 50; m++)
{
n = m + m;
tempstr[0] = Keycheck[n];
tempstr[1] = Keycheck[n+1];
buf[m] = (int)strtol(tempstr, NULL, 16);
}
if (cryptit(buf) == FAIL)
return (FAIL);
for (m = 0; m < 50; m++) {
if (buf[m] > 0177) {
char msg[PATHSIZ + 30];
sprintf(msg, "Key does not unscramble %s",
entry->dname);
mess_temp(msg);
return (FAIL); /* encrypted */
}
}
return (SUCCESS); /* not encrypted */
}
static int
mkencrypart()
{
register int n, m;
char tempstr[3];
unsigned char buf[51];
unsigned int left, right;
time_t clock; /* EFT abs k16 */
clock = time((time_t *)0); /* EFT abs k16 */
right = clock & 0177;
buf[0] = right;
for (n = 1; n < 50; n++) {
right = (right + n + (right & 0125)) & 0177;
if (right == 0177) right = n;
buf[n] = right;
}
if (cryptit(buf) == FAIL)
return (FAIL);
for (m = 0; m < 50; m++) {
static char hex[] = "0123456789abcdef";
n = m * 2;
Keycheck[n] = hex[(buf[m] >> 4) & 0xf];
Keycheck[n+1] = hex[buf[m] & 0xf];
}
Keycheck[KEYSIZE - 1] = '\0';
return (SUCCESS);
}
static int
cryptit(buf)
char *buf;
{
int fd;
char efile[20], dfile[20];
char action[(2 * PATHSIZ) + 80];
strcpy(dfile, "/tmp/.DECXXXXXX");
strcpy(efile, "/tmp/.ENCXXXXXX");
if ((fd = mkstemp(efile)) < 0)
fatal(NOPEN, efile);
write(fd, buf, 50);
(void) close(fd);
if ((fd = mkstemp(dfile)) < 0)
fatal(NOPEN, dfile);
(void) close(fd);
sprintf(action, "crypt '%s' < %s > %s", Passwd, efile, dfile);
if (waitspawn(sysspawn(action)) != 0) {
mess_temp("Encryption software not available");
(void) unlink(efile);
(void) unlink(dfile);
return (FAIL);
}
unlink(efile);
if ((fd = open(dfile, O_RDONLY)) < 0)
fatal(NOPEN, dfile);
read(fd, buf, 50);
(void) close(fd);
(void) unlink(dfile);
return (SUCCESS);
}