1/* 2 * Frontend command-line utility for Linux NVRAM layer 3 * 4 * Copyright (C) 2012, Broadcom Corporation. All Rights Reserved. 5 * 6 * Permission to use, copy, modify, and/or distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 13 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 15 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 16 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 * 18 * $Id: main.c 325698 2012-04-04 12:40:07Z $ 19 */ 20 21#include <stdio.h> 22#include <stdlib.h> 23#include <string.h> 24 25#include <typedefs.h> 26#include <rtconfig.h> 27#include <bcmnvram.h> 28 29 30#define PROFILE_HEADER "HDR1" 31#ifdef RTCONFIG_DSL 32#define PROFILE_HEADER_NEW "N55U" 33#else 34#define PROFILE_HEADER_NEW "HDR2" 35#endif 36 37/******************************************************************* 38* NAME: _secure_romfile 39* AUTHOR: Andy Chiu 40* CREATE DATE: 2015/06/08 41* DESCRIPTION: replace account /password by '1' with the same string length 42* INPUT: path: the rom file path 43* OUTPUT: 44* RETURN: 0: success, -1:failed 45* NOTE: Andy Chiu, 2015/12/18. Add new tokens. 46* Andy Chiu, 2015/12/24. Add new tokens. 47* Andy Chiu, 2016/02/18. Add new token, wtf_username. 48*******************************************************************/ 49static int _secure_conf(char* buf) 50{ 51 char name[128], *item; 52 int i, flag; 53 const char *keyword_token[] = {"http_username", "pppoe_username", "passwd", "password", ""}; //Andy Chiu, 2015/12/18 54 55 const char *token1[] = {"wan_pppoe_passwd", "modem_pass", "modem_pincode", 56 "http_passwd", "wan0_pppoe_passwd", "dslx_pppoe_passwd", "ddns_passwd_x", 57 "wl_wpa_psk", "wlc_wpa_psk", "wlc_wep_key", 58 "wl0_wpa_psk", "wl0.1_wpa_psk", "wl0.2_wpa_psk", "wl0.3_wpa_psk", 59 "wl1_wpa_psk", "wl1.1_wpa_psk", "wl1.2_wpa_psk", "wl1.3_wpa_psk", 60 "wl0.1_key1", "wl0.1_key2", "wl0.1_key3", "wl0.1_key4", 61 "wl0.2_key1", "wl0.2_key2", "wl0.2_key3", "wl0.2_key4", 62 "wl0.3_key1", "wl0.3_key2", "wl0.3_key3", "wl0.3_key4", 63 "wl0_key1", "wl0_key2", "wl0_key3", "wl0_key4", 64 "wl1.1_key1", "wl1.1_key2", "wl1.1_key3", "wl1.1_key4", 65 "wl1.2_key1", "wl1.2_key2", "wl1.2_key3", "wl1.2_key4", 66 "wl1.3_key1", "wl1.3_key2", "wl1.3_key3", "wl1.3_key4", 67 "wl_key1", "wl_key2", "wl_key3", "wl_key4", 68 "wl1_key1", "wl1_key2", "wl1_key3", "wl1_key4", 69 "wl0_phrase_x", "wl0.1_phrase_x", "wl0.2_phrase_x", "wl0.3_phrase_x", 70 "wl1_phrase_x", "wl1.1_phrase_x", "wl1.2_phrase_x", "wl1.3_phrase_x", 71 "wl_phrase_x", "vpnc_openvpn_pwd", "PM_SMTP_AUTH_USER", "PM_MY_EMAIL", "PM_SMTP_AUTH_PASS", "wtf_username", ""}; 72 73 const char *token2[] = {"acc_list", "pptpd_clientlist", ""}; 74 //admin>99999<Family>99999999<aaaaa>9999999<bbbbb>999999 75 //pptpd_clientlist=<aaaaaaaaa>999999999<bbbbbbbbbb>9999999999 76 77 const char vpnc_token[] = "vpnc_clientlist"; 78// qwrety>PPTP>asdf>aaaaaaaaaa>999999999999<qe3rtuio>L2TP>waesrdio>bbbbbbbbb>9999999999999<wqertuio>OpenVPN>1>ccccccccc>999999999999 79 80 const char cloud_token[] = "cloud_sync"; 81// 0>aaaaaaaaaaa>9999999999>none>0>/tmp/mnt/SANDISK_32G/aaa>1 82 83 if(!buf) 84 return -1; 85 86 //fprintf(stderr, "[%s, %d]\n", __FUNCTION__, __LINE__); 87 for (item = buf; *item; item += strlen(item) + 1) 88 { 89 //get name of item 90 char *ptr = strchr(item, '='); 91 if(!ptr) //invalid item 92 continue; 93 memset(name, 0, sizeof(name)); 94 strncpy(name, item, ptr - item); 95 flag = 0; 96 //skip '=' 97 ++ptr; 98 //fprintf(stderr, "[%s, %d]item(%s), name(%s), val(%s)\n", __FUNCTION__, __LINE__, item, name, ptr); 99 100 //check the password keyword token 101 for(i = 0; strlen(keyword_token[i]) > 0; ++i) 102 { 103 if(strstr(name, keyword_token[i])) 104 { 105 //replace the value 106 memset(ptr, '1', strlen(ptr)); 107 //fprintf(stderr, "[%s, %d]<%s>replace(%s)\n", __FUNCTION__, __LINE__, name, ptr); 108 flag = 1; 109 break; 110 } 111 } 112 if(flag) 113 continue; 114 115 //check the first token group 116 for(i = 0; strlen(token1[i]) > 0; ++i) 117 { 118 if(!strcmp(name, token1[i])) 119 { 120 //replace the value 121 memset(ptr, '1', strlen(ptr)); 122 //fprintf(stderr, "[%s, %d]<%s>replace(%s)\n", __FUNCTION__, __LINE__, name, ptr); 123 flag = 1; 124 break; 125 } 126 } 127 if(flag) 128 continue; 129 130 //check the 2nd token group 131 //admin>99999<Family>99999999<aaaaa>9999999<bbbbb>999999 132 for(i = 0; strlen(token2[i]) > 0; ++i) 133 { 134 if(!strcmp(name, token2[i])) 135 { 136 //replace the value 137 char *b = ptr, *e; 138 do 139 { 140 b = strchr(b, '>'); 141 if(b) 142 ++b; 143 else 144 break; 145 e = strchr(b, '<'); 146 147 if(e) 148 { 149 memset(b, '1', e-b); 150 b = e + 1; 151 } 152 else 153 memset(b, '1', strlen(b)); 154 155 }while(b); 156 //fprintf(stderr, "[%s, %d]<%s>replace(%s)\n", __FUNCTION__, __LINE__, name, ptr); 157 flag = 1; 158 break; 159 } 160 } 161 if(flag) 162 continue; 163 164 //check vpnc token 165 //qwrety>PPTP>asdf>aaaaaaaaaa>999999999999<qe3rtuio>L2TP>waesrdio>bbbbbbbbb>9999999999999<wqertuio>OpenVPN>1>ccccccccc>999999999999 166 if(!strcmp(name, vpnc_token)) 167 { 168 char *b = ptr, *e; 169 if(*b == '<') 170 ++b; 171 do{ 172 int j; 173 for(j = 0; j < 4; ++j) 174 { 175 b = strchr(b, '>'); 176 if(b) 177 ++b; 178 else 179 break; 180 } 181 182 if(b) 183 { 184 e = strchr(b, '<'); 185 if(e) 186 { 187 memset(b, '1', e - b); 188 b = e + 1; 189 } 190 else 191 { 192 memset(b, '1', strlen(b)); 193 b = NULL; 194 } 195 } 196 }while(b); 197 //fprintf(stderr, "[%s, %d]<%s>replace(%s)\n", __FUNCTION__, __LINE__, name, ptr); 198 } 199 200 //check cloud sync token 201 //0>aaaaaaaaaaa>9999999999>none>0>/tmp/mnt/SANDISK_32G/aaa>1 202 if(!strcmp(name, cloud_token)) 203 { 204 char *b = ptr, *e; 205 if(*b == '<') 206 ++b; 207 do{ 208 int j; 209 for(j = 0; j < 2; ++j) 210 { 211 b = strchr(b, '>'); 212 if(b) 213 ++b; 214 else 215 break; 216 } 217 218 if(b) 219 { 220 e = strchr(b, '>'); 221 if(e) 222 { 223 memset(b, '1', e - b); 224 b = strchr(e, '<'); 225 } 226 else //invalid 227 { 228 b = NULL; 229 } 230 } 231 }while(b); 232 //fprintf(stderr, "[%s, %d]<%s>replace(%s)\n", __FUNCTION__, __LINE__, name, ptr); 233 } 234 } 235 return 0; 236} 237 238 239unsigned char get_rand() 240{ 241 unsigned char buf[1]; 242 FILE *fp; 243 244 fp = fopen("/dev/urandom", "r"); 245 if (fp == NULL) { 246#ifdef ASUS_DEBUG 247 fprintf(stderr, "Could not open /dev/urandom.\n"); 248#endif 249 return 0; 250 } 251 fread(buf, 1, 1, fp); 252 fclose(fp); 253 254 return buf[0]; 255} 256 257int nvram_save_new(char *file, char *buf) 258{ 259 FILE *fp; 260 char *name; 261 unsigned long count, filelen, i; 262 unsigned char rand = 0, temp; 263 264 if ((fp = fopen(file, "w")) == NULL) return -1; 265 266 count = 0; 267 for (name = buf; *name; name += strlen(name) + 1) 268 { 269#ifdef ASUS_DEBUG 270 puts(name); 271#endif 272 count = count + strlen(name) + 1; 273 } 274 275 filelen = count + (1024 - count % 1024); 276 rand = get_rand() % 30; 277#ifdef ASUS_DEBUG 278 fprintf(stderr, "random number: %x\n", rand); 279#endif 280 fwrite(PROFILE_HEADER_NEW, 1, 4, fp); 281 fwrite(&filelen, 1, 3, fp); 282 fwrite(&rand, 1, 1, fp); 283#ifdef ASUS_DEBUG 284 for (i = 0; i < 4; i++) 285 { 286 fprintf(stderr, "%2x ", PROFILE_HEADER_NEW[i]); 287 } 288 for (i = 0; i < 3; i++) 289 { 290 fprintf(stderr, "%2x ", ((char *)&filelen)[i]); 291 } 292 fprintf(stderr, "%2x ", ((char *)&rand)[0]); 293#endif 294 for (i = 0; i < count; i++) 295 { 296 if (buf[i] == 0x0) 297 buf[i] = 0xfd + get_rand() % 3; 298 else 299 buf[i] = 0xff - buf[i] + rand; 300 } 301 fwrite(buf, 1, count, fp); 302#ifdef ASUS_DEBUG 303 for (i = 0; i < count; i++) 304 { 305 if (i % 16 == 0) fprintf(stderr, "\n"); 306 fprintf(stderr, "%2x ", (unsigned char) buf[i]); 307 } 308#endif 309 for (i = count; i < filelen; i++) 310 { 311 temp = 0xfd + get_rand() % 3; 312 fwrite(&temp, 1, 1, fp); 313#ifdef ASUS_DEBUG 314 if (i % 16 == 0) fprintf(stderr, "\n"); 315 fprintf(stderr, "%2x ", (unsigned char) temp); 316#endif 317 } 318 fclose(fp); 319 return 0; 320} 321 322int issyspara(char *p) 323{ 324 struct nvram_tuple *t; 325 extern struct nvram_tuple router_defaults[]; 326 327 // skip checking for wl[]_, wan[], lan[]_ 328 if (strstr(p, "wl") || strstr(p, "wan") || strstr(p, "lan")) 329 return 1; 330 331 for (t = router_defaults; t->name; t++) 332 { 333 if (strstr(p, t->name)) 334 break; 335 336 } 337 338 if (t->name) return 1; 339 else return 0; 340} 341 342int nvram_restore_new(char *file, char *buf) 343{ 344 FILE *fp; 345 char header[8], *p, *v; 346 unsigned long count, filelen, *filelenptr, i; 347 unsigned char rand, *randptr; 348 349 if ((fp = fopen(file, "r+")) == NULL) return -1; 350 351 count = fread(header, 1, 8, fp); 352 if (count>=8 && strncmp(header, PROFILE_HEADER, 4) == 0) 353 { 354 filelenptr = (unsigned long *)(header + 4); 355#ifdef ASUS_DEBUG 356 fprintf(stderr, "restoring original text cfg of length %x\n", *filelenptr); 357#endif 358 fread(buf, 1, *filelenptr, fp); 359 } 360 else if (count>=8 && strncmp(header, PROFILE_HEADER_NEW, 4) == 0) 361 { 362 filelenptr = (unsigned long *)(header + 4); 363 filelen = *filelenptr & 0xffffff; 364#ifdef ASUS_DEBUG 365 fprintf(stderr, "restoring non-text cfg of length %x\n", filelen); 366#endif 367 randptr = (unsigned char *)(header + 7); 368 rand = *randptr; 369#ifdef ASUS_DEBUG 370 fprintf(stderr, "non-text cfg random number %x\n", rand); 371#endif 372 count = fread(buf, 1, filelen, fp); 373#ifdef ASUS_DEBUG 374 fprintf(stderr, "non-text cfg count %x\n", count); 375#endif 376 for (i = 0; i < count; i++) 377 { 378 if ((unsigned char) buf[i] > ( 0xfd - 0x1)){ 379 /* e.g.: to skip the case: 0x61 0x62 0x63 0x00 0x00 0x61 0x62 0x63 */ 380 if(i > 0 && buf[i-1] != 0x0) 381 buf[i] = 0x0; 382 } 383 else 384 buf[i] = 0xff + rand - buf[i]; 385 } 386#ifdef ASUS_DEBUG 387 for (i = 0; i < count; i++) 388 { 389 if (i % 16 == 0) fprintf(stderr, "\n"); 390 fprintf(stderr, "%2x ", (unsigned char) buf[i]); 391 } 392 393 for (i = 0; i < count; i++) 394 { 395 if (i % 16 == 0) fprintf(stderr, "\n"); 396 fprintf(stderr, "%c", buf[i]); 397 } 398#endif 399 } 400 else 401 { 402 fclose(fp); 403 return 0; 404 } 405 fclose(fp); 406 407 p = buf; 408 409 while (*p) 410 { 411#if 1 412 /* e.g.: to skip the case: 00 2e 30 2e 32 38 00 ff 77 61 6e */ 413 if(*p == NULL || *p < 32 || *p > 127 ){ 414 p = p + 1; 415 continue; 416 } 417#endif 418 v = strchr(p, '='); 419 420 if (v != NULL) 421 { 422 *v++ = '\0'; 423 424 if (issyspara(p)) 425 nvram_set(p, v); 426 427 p = v + strlen(v) + 1; 428 } 429 else 430 { 431 nvram_unset(p); 432 p = p + 1; 433 } 434 } 435 return 0; 436} 437 438void 439usage(void) 440{ 441 fprintf(stderr, 442 "usage: nvram [get name] [set name=value] " 443 "[unset name] [show] [commit] [save] [restore] [erase][fb_save file] ...\n"); 444 exit(0); 445} 446 447/* NVRAM utility */ 448int 449main(int argc, char **argv) 450{ 451 char *name, *value, buf[MAX_NVRAM_SPACE]; 452 char *tmpbuf; //Andy Chiu, 2015/06/09 453 int size; 454 455 /* Skip program name */ 456 --argc; 457 ++argv; 458 459 if (!*argv) 460 usage(); 461 462 /* Process the arguments */ 463 for (; *argv; ++argv) { 464 if (!strcmp(*argv, "get")) { 465 if (*++argv) { 466 if ((value = nvram_get(*argv))) 467 puts(value); 468 } 469 } else if (!strcmp(*argv, "set")) { 470 if (*++argv) { 471 strncpy(value = buf, *argv, sizeof(buf)); 472 name = strsep(&value, "="); 473 nvram_set(name, value); 474 } 475 } else if (!strcmp(*argv, "unset")) { 476 if (*++argv) 477 nvram_unset(*argv); 478 } else if (!strcmp(*argv, "commit")) { 479 nvram_commit(); 480 } else if (!strcmp(*argv, "save")) { 481 if (*++argv) 482 { 483 nvram_getall(buf, NVRAM_SPACE); 484 nvram_save_new(*argv, buf); 485 } 486 //Andy Chiu, 2015/06/09 487 }else if(!strncmp(*argv, "fb_save", 7)) { 488 if (*++argv) 489 { 490 tmpbuf = malloc(MAX_NVRAM_SPACE); 491 if(!tmpbuf) 492 { 493 fprintf(stderr, "Can NOT alloc memory!!!"); 494 return 0; 495 } 496 nvram_getall(buf, MAX_NVRAM_SPACE); 497 memcpy(tmpbuf, buf, MAX_NVRAM_SPACE); 498 _secure_conf(tmpbuf); 499#if 0 500 FILE *fp = fopen("/tmp/var/fb_conf.test", "w"); 501 if(fp) 502 { 503 fwrite(tmpbuf, 1, MAX_NVRAM_SPACE, fp); 504 fclose(fp); 505 } 506#endif 507 nvram_save_new(*argv, tmpbuf); 508 free(tmpbuf); 509 } 510 } else if (!strcmp(*argv, "restore")) { 511 if (*++argv) 512 nvram_restore_new(*argv, buf); 513 } else if (!strcmp(*argv, "erase")) { 514 system("nvram_erase"); 515 } else if (!strcmp(*argv, "show") || 516 !strcmp(*argv, "dump")) { 517 nvram_getall(buf, sizeof(buf)); 518 for (name = buf; *name; name += strlen(name) + 1) 519 puts(name); 520 size = sizeof(struct nvram_header) + (int) name - (int) buf; 521 if (**argv != 'd') 522 fprintf(stderr, "size: %d bytes (%d left)\n", 523 size, MAX_NVRAM_SPACE - size); 524 } else 525 usage(); 526 } 527 528 return 0; 529} 530