1129590Smarius/*- 2129590Smarius * Copyright (c) 2004 Marius Strobl 3129590Smarius * All rights reserved. 4129590Smarius * 5129590Smarius * Redistribution and use in source and binary forms, with or without 6129590Smarius * modification, are permitted provided that the following conditions 7129590Smarius * are met: 8129590Smarius * 1. Redistributions of source code must retain the above copyright 9129590Smarius * notice, this list of conditions and the following disclaimer. 10129590Smarius * 2. Redistributions in binary form must reproduce the above copyright 11129590Smarius * notice, this list of conditions and the following disclaimer in the 12129590Smarius * documentation and/or other materials provided with the distribution. 13129590Smarius * 14129590Smarius * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15129590Smarius * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16129590Smarius * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17129590Smarius * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 18129590Smarius * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19129590Smarius * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20129590Smarius * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21129590Smarius * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22129590Smarius * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 23129590Smarius * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24129590Smarius */ 25129590Smarius 26129590Smarius#include <sys/cdefs.h> 27129590Smarius__FBSDID("$FreeBSD$"); 28129590Smarius 29129590Smarius/* 30129590Smarius * Handlers for Open Firmware /options node. 31129590Smarius */ 32129590Smarius 33129590Smarius#include <sys/types.h> 34129590Smarius 35129590Smarius#include <dev/ofw/openfirm.h> 36129590Smarius 37129590Smarius#include <err.h> 38129590Smarius#include <fcntl.h> 39129590Smarius#include <readpassphrase.h> 40129590Smarius#include <stdio.h> 41129590Smarius#include <stdlib.h> 42129590Smarius#include <string.h> 43129590Smarius#include <sysexits.h> 44129590Smarius#include <unistd.h> 45129590Smarius 46129590Smarius#include "ofw_options.h" 47129590Smarius#include "ofw_util.h" 48129590Smarius 49129590Smarius#define OFWO_LOGO 512 50129590Smarius#define OFWO_MAXPROP 31 51129590Smarius#define OFWO_MAXPWD 8 52129590Smarius 53129590Smariusstruct ofwo_extabent { 54129590Smarius const char *ex_prop; 55190097Smarius int (*ex_handler)(const struct ofwo_extabent *, int, 56190097Smarius const void *, int, const char *); 57129590Smarius}; 58129590Smarius 59190097Smariusstatic int ofwo_oemlogo(const struct ofwo_extabent *, int, const void *, 60190097Smarius int, const char *); 61190097Smariusstatic int ofwo_secmode(const struct ofwo_extabent *, int, const void *, 62190097Smarius int, const char *); 63190097Smariusstatic int ofwo_secpwd(const struct ofwo_extabent *, int, const void *, 64190097Smarius int, const char *); 65129590Smarius 66263763Sdimstatic const struct ofwo_extabent ofwo_extab[] = { 67129590Smarius { "oem-logo", ofwo_oemlogo }, 68129590Smarius { "security-mode", ofwo_secmode }, 69129590Smarius { "security-password", ofwo_secpwd }, 70129590Smarius { NULL, NULL } 71129590Smarius}; 72129590Smarius 73161834Smariusstatic int ofwo_setpass(int); 74161834Smariusstatic int ofwo_setstr(int, const void *, int, const char *, const char *); 75129590Smarius 76132788Skanstatic __inline void 77132788Skanofwo_printprop(const char *prop, const char* buf, int buflen) 78132788Skan{ 79132788Skan 80132788Skan printf("%s: %.*s\n", prop, buflen, buf); 81132788Skan} 82132788Skan 83129590Smariusstatic int 84190097Smariusofwo_oemlogo(const struct ofwo_extabent *exent, int fd, const void *buf, 85190097Smarius int buflen, const char *val) 86129590Smarius{ 87129590Smarius int lfd; 88129590Smarius char logo[OFWO_LOGO + 1]; 89129590Smarius 90129590Smarius if (val) { 91129590Smarius if (val[0] == '\0') 92129590Smarius ofw_setprop(fd, ofw_optnode(fd), exent->ex_prop, "", 1); 93129590Smarius else { 94129590Smarius if ((lfd = open(val, O_RDONLY)) == -1) { 95129590Smarius warn("could not open '%s'", val); 96129590Smarius return (EX_USAGE); 97129590Smarius } 98129590Smarius if (read(lfd, logo, OFWO_LOGO) != OFWO_LOGO || 99129590Smarius lseek(lfd, 0, SEEK_END) != OFWO_LOGO) { 100129590Smarius close(lfd); 101129590Smarius warnx("logo '%s' has wrong size.", val); 102129590Smarius return (EX_USAGE); 103129590Smarius } 104129590Smarius close(lfd); 105129590Smarius logo[OFWO_LOGO] = '\0'; 106129590Smarius if (ofw_setprop(fd, ofw_optnode(fd), exent->ex_prop, 107129590Smarius logo, OFWO_LOGO + 1) != OFWO_LOGO) 108129590Smarius errx(EX_IOERR, "writing logo failed."); 109129590Smarius } 110129590Smarius } else 111129590Smarius if (buflen != 0) 112129590Smarius printf("%s: <logo data>\n", exent->ex_prop); 113129590Smarius else 114129590Smarius ofwo_printprop(exent->ex_prop, (const char *)buf, 115129590Smarius buflen); 116129590Smarius return (EX_OK); 117129590Smarius} 118129590Smarius 119129590Smariusstatic int 120190097Smariusofwo_secmode(const struct ofwo_extabent *exent, int fd, const void *buf, 121190097Smarius int buflen, const char *val) 122129590Smarius{ 123129590Smarius int res; 124129590Smarius 125129590Smarius if (val) { 126129590Smarius if (strcmp(val, "full") == 0 || strcmp(val, "command") == 0) { 127129590Smarius if ((res = ofwo_setpass(fd)) != EX_OK) 128129590Smarius return (res); 129129590Smarius if ((res = ofwo_setstr(fd, buf, buflen, exent->ex_prop, 130129590Smarius val)) != EX_OK) 131129590Smarius ofw_setprop(fd, ofw_optnode(fd), 132129590Smarius "security-password", "", 1); 133129590Smarius return (res); 134129590Smarius } 135129590Smarius if (strcmp(val, "none") == 0) { 136129590Smarius ofw_setprop(fd, ofw_optnode(fd), "security-password", 137129590Smarius "", 1); 138129590Smarius return (ofwo_setstr(fd, buf, buflen, exent->ex_prop, 139129590Smarius val)); 140129590Smarius } 141129590Smarius return (EX_DATAERR); 142129590Smarius } else 143129590Smarius ofwo_printprop(exent->ex_prop, (const char *)buf, buflen); 144129590Smarius return (EX_OK); 145129590Smarius} 146129590Smarius 147129590Smariusstatic int 148190097Smariusofwo_secpwd(const struct ofwo_extabent *exent, int fd, const void *buf, 149190097Smarius int buflen, const char *val) 150129590Smarius{ 151129590Smarius void *pbuf; 152129590Smarius int len, pblen, rv; 153129590Smarius 154129590Smarius pblen = 0; 155129590Smarius rv = EX_OK; 156129590Smarius pbuf = NULL; 157129590Smarius if (val) { 158129590Smarius len = ofw_getprop_alloc(fd, ofw_optnode(fd), "security-mode", 159129590Smarius &pbuf, &pblen, 1); 160129590Smarius if (len <= 0 || strncmp("none", (char *)pbuf, len) == 0) { 161129590Smarius rv = EX_CONFIG; 162129590Smarius warnx("no security mode set."); 163129590Smarius } else if (strncmp("command", (char *)pbuf, len) == 0 || 164129590Smarius strncmp("full", (char *)pbuf, len) == 0) { 165129590Smarius rv = ofwo_setpass(fd); 166129590Smarius } else { 167129590Smarius rv = EX_CONFIG; 168129590Smarius warnx("invalid security mode."); 169129590Smarius } 170129590Smarius } else 171129590Smarius ofwo_printprop(exent->ex_prop, (const char *)buf, buflen); 172129590Smarius if (pbuf != NULL) 173129590Smarius free(pbuf); 174129590Smarius return (rv); 175129590Smarius} 176129590Smarius 177129590Smariusstatic int 178129590Smariusofwo_setpass(int fd) 179129590Smarius{ 180129590Smarius char pwd1[OFWO_MAXPWD + 1], pwd2[OFWO_MAXPWD + 1]; 181129590Smarius 182129590Smarius if (readpassphrase("New password:", pwd1, sizeof(pwd1), 183129590Smarius RPP_ECHO_OFF | RPP_REQUIRE_TTY) == NULL || 184129590Smarius readpassphrase("Retype new password:", pwd2, sizeof(pwd2), 185129590Smarius RPP_ECHO_OFF | RPP_REQUIRE_TTY) == NULL) 186129590Smarius errx(EX_USAGE, "failed to get password."); 187129590Smarius if (strlen(pwd1) == 0) { 188129590Smarius printf("Password unchanged.\n"); 189129590Smarius return (EX_OK); 190129590Smarius } 191129590Smarius if (strcmp(pwd1, pwd2) != 0) { 192129590Smarius printf("Mismatch - password unchanged.\n"); 193129590Smarius return (EX_USAGE); 194129590Smarius } 195129590Smarius ofw_setprop(fd, ofw_optnode(fd), "security-password", pwd1, 196129590Smarius strlen(pwd1) + 1); 197129590Smarius return (EX_OK); 198129590Smarius} 199129590Smarius 200129590Smariusstatic int 201129590Smariusofwo_setstr(int fd, const void *buf, int buflen, const char *prop, 202129590Smarius const char *val) 203129590Smarius{ 204129590Smarius void *pbuf; 205129590Smarius int len, pblen, rv; 206129590Smarius phandle_t optnode; 207129590Smarius char *oval; 208129590Smarius 209129590Smarius pblen = 0; 210129590Smarius rv = EX_OK; 211129590Smarius pbuf = NULL; 212129590Smarius optnode = ofw_optnode(fd); 213129590Smarius ofw_setprop(fd, optnode, prop, val, strlen(val) + 1); 214129590Smarius len = ofw_getprop_alloc(fd, optnode, prop, &pbuf, &pblen, 1); 215129590Smarius if (len < 0 || strncmp(val, (char *)pbuf, len) != 0) { 216129590Smarius /* 217129590Smarius * The value is too long for this property and the OFW has 218129590Smarius * truncated it to fit or the value is illegal and a legal 219129590Smarius * one has been written instead (e.g. attempted to write 220129590Smarius * "foobar" to a "true"/"false"-property) - try to recover 221129590Smarius * the old value. 222129590Smarius */ 223129590Smarius rv = EX_DATAERR; 224129590Smarius if ((oval = malloc(buflen + 1)) == NULL) 225129590Smarius err(EX_OSERR, "malloc() failed."); 226129590Smarius strncpy(oval, buf, buflen); 227129590Smarius oval[buflen] = '\0'; 228129590Smarius len = ofw_setprop(fd, optnode, prop, oval, buflen + 1); 229129590Smarius if (len != buflen) 230129590Smarius errx(EX_IOERR, "recovery of old value failed."); 231129590Smarius free(oval); 232129590Smarius goto out; 233129590Smarius } 234129590Smarius printf("%s: %.*s%s->%s%.*s\n", prop, buflen, (const char *)buf, 235129590Smarius buflen > 0 ? " " : "", len > 0 ? " " : "", len, (char *)pbuf); 236129590Smariusout: 237129590Smarius if (pbuf != NULL) 238129590Smarius free(pbuf); 239129590Smarius return (rv); 240129590Smarius} 241129590Smarius 242129590Smariusvoid 243129590Smariusofwo_dump(void) 244129590Smarius{ 245129590Smarius void *pbuf; 246129590Smarius int fd, len, nlen, pblen; 247129590Smarius phandle_t optnode; 248129590Smarius char prop[OFWO_MAXPROP + 1]; 249190097Smarius const struct ofwo_extabent *ex; 250129590Smarius 251129590Smarius pblen = 0; 252129590Smarius pbuf = NULL; 253129590Smarius fd = ofw_open(O_RDONLY); 254129590Smarius optnode = ofw_optnode(fd); 255129590Smarius for (nlen = ofw_firstprop(fd, optnode, prop, sizeof(prop)); nlen != 0; 256190097Smarius nlen = ofw_nextprop(fd, optnode, prop, prop, sizeof(prop))) { 257129590Smarius len = ofw_getprop_alloc(fd, optnode, prop, &pbuf, &pblen, 1); 258129590Smarius if (len < 0) 259129590Smarius continue; 260129590Smarius if (strcmp(prop, "name") == 0) 261129590Smarius continue; 262129590Smarius for (ex = ofwo_extab; ex->ex_prop != NULL; ++ex) 263129590Smarius if (strcmp(ex->ex_prop, prop) == 0) 264129590Smarius break; 265129590Smarius if (ex->ex_prop != NULL) 266129590Smarius (*ex->ex_handler)(ex, fd, pbuf, len, NULL); 267129590Smarius else 268129590Smarius ofwo_printprop(prop, (char *)pbuf, len); 269129590Smarius } 270129590Smarius if (pbuf != NULL) 271129590Smarius free(pbuf); 272129590Smarius ofw_close(fd); 273129590Smarius} 274129590Smarius 275129590Smariusint 276129590Smariusofwo_action(const char *prop, const char *val) 277129590Smarius{ 278129590Smarius void *pbuf; 279129590Smarius int fd, len, pblen, rv; 280190097Smarius const struct ofwo_extabent *ex; 281129590Smarius 282129590Smarius pblen = 0; 283129590Smarius rv = EX_OK; 284129590Smarius pbuf = NULL; 285129590Smarius if (strcmp(prop, "name") == 0) 286129590Smarius return (EX_UNAVAILABLE); 287129590Smarius if (val) 288129590Smarius fd = ofw_open(O_RDWR); 289129590Smarius else 290129590Smarius fd = ofw_open(O_RDONLY); 291133768Smarius len = ofw_getprop_alloc(fd, ofw_optnode(fd), prop, &pbuf, &pblen, 1); 292129590Smarius if (len < 0) { 293129590Smarius rv = EX_UNAVAILABLE; 294129590Smarius goto out; 295129590Smarius } 296129590Smarius for (ex = ofwo_extab; ex->ex_prop != NULL; ++ex) 297129590Smarius if (strcmp(ex->ex_prop, prop) == 0) 298129590Smarius break; 299129590Smarius if (ex->ex_prop != NULL) 300129590Smarius rv = (*ex->ex_handler)(ex, fd, pbuf, len, val); 301129590Smarius else if (val) 302129590Smarius rv = ofwo_setstr(fd, pbuf, len, prop, val); 303190097Smarius else 304129590Smarius ofwo_printprop(prop, (char *)pbuf, len); 305129590Smariusout: 306129590Smarius if (pbuf != NULL) 307129590Smarius free(pbuf); 308129590Smarius ofw_close(fd); 309129590Smarius return (rv); 310129590Smarius} 311