SIP Witch 1.9.15
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
sippasswd.cpp
Go to the documentation of this file.
1 // Copyright (C) 2010-2014 David Sugar, Tycho Softworks.
2 // Copyright (C) 2015 Cherokees of Idaho.
3 //
4 // This program is free software; you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation; either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
16 
17 #include <sipwitch-config.h>
18 #include <ucommon/ucommon.h>
19 #include <ucommon/secure.h>
20 #include <sipwitch/sipwitch.h>
21 #ifdef HAVE_PWD_H
22 #include <pwd.h>
23 #endif
24 
25 using namespace sipwitch;
26 
27 #ifdef _MSWINDOWS_
28 #include <io.h>
29 static char *getpass(const char *prompt)
30 {
31  static char buf[128];
32  size_t i;
33 
34  fputs(prompt, stderr);
35  fflush(stderr);
36  for (i = 0; i < sizeof(buf) - 1; i++) {
37  buf[i] = fgetc(stdin);
38  if (buf[i] == '\r' || buf[i] == '\n')
39  break;
40  fputs("*", stderr);
41  fflush(stderr);
42  }
43  buf[i] = 0;
44  fputs("\n", stderr);
45  fflush(stderr);
46  return buf;
47 }
48 #endif
49 
51 {
52  const char *realm = NULL, *secret, *verify;
53  const char *mode = "md5";
54  char buffer[128];
55  char replace[128];
56  string_t digestbuf;
57  fpos_t pos;
58  FILE *fp;
59 
60 #ifdef _MSWINDOWS_
61  const char *control = "\\\\.\\mailslot\\sipwitch_ctrl";
62 #else
63  const char *control = DEFAULT_VARPATH "/run/sipwitch/control";
64 #endif
65 
66  const char *user = *(++argv);
67 
68  if(String::equal(user, "-version")) {
69  printf("sippasswd 0.1\n"
70  "Copyright (C) 2010 David Sugar, Tycho Softworks\n"
71  "License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\n"
72  "This is free software: you are free to change and redistribute it.\n"
73  "There is NO WARRANTY, to the extent permitted by law.\n");
74  exit(0);
75  }
76 
77 #ifdef HAVE_PWD_H
78  if(user && getuid() != 0)
79  shell::errexit(3, "*** sippasswd: only root can change other user's digests\n");
80 
81  if(!user) {
82  struct passwd *pwd = getpwuid(getuid());
83  if(!pwd)
84  shell::errexit(3, "*** sippasswd: user id cannot be determined\n");
85 
86  user = strdup(pwd->pw_name);
87  }
88  if(geteuid() != 0)
89  shell::errexit(3, "*** sippasswd: root privilege required\n");
90 #else
91  if(!user)
92  shell::errexit(3, "*** sippasswd: user id not specified\n");
93 
94 #endif
95 
96  fsys_t fs;
97  fs.open(DEFAULT_CFGPATH "/siprealm", fsys::RDONLY);
98 
99  if(!is(fs))
100  fs.open(DEFAULT_VARPATH "/lib/sipwitch/uuid", fsys::RDONLY);
101 
102  if(!is(fs))
103  shell::errexit(4, "*** sippasswd: no realm active\n");
104 
105  memset(buffer, 0, sizeof(buffer));
106  fs.read(buffer, sizeof(buffer) - 1);
107  fs.close();
108 
109  char *cp = strchr(buffer, '\n');
110  if(cp)
111  *cp = 0;
112 
113  cp = strchr(buffer, ':');
114  if(cp)
115  *(cp++) = 0;
116 
117  if(cp && *cp)
118  mode = cp;
119 
120  realm = strdup(buffer);
121  secret = getpass("Enter new SIP secret: ");
122  if(!secret || !*secret) {
123  printf("no password supplied\n");
124  exit(0);
125  }
126 
127  verify = getpass("Retype new SIP secret: ");
128  if(!verify || !*verify || !String::equal(secret, verify)) {
129  printf("sorry, secrets do not match\n");
130  exit(0);
131  }
132 
133  digest_t digest(mode);
134 
135  if(!digest.puts((string_t)user + ":" + (string_t)realm + ":" + (string_t)secret))
136  shell::errexit(1, "*** sippasswd: cannot compute");
137  else
138  digestbuf = *digest;
139 
140  snprintf(replace, sizeof(replace), "%s:%s\n", user, *digestbuf);
141 
142  // create work directory if it does not exist
143  dir::create(DEFAULT_VARPATH "/lib/sipwitch", fsys::GROUP_PRIVATE);
144  dir::create(DEFAULT_VARPATH "/lib/sipwitch/digests", fsys::GROUP_PRIVATE);
145 
146  // make sure always created root only
147  string_t path = str(DEFAULT_VARPATH "/lib/sipwitch/digests/") + realm;
148  fs.open(*path, fsys::OWNER_PRIVATE, fsys::RDONLY);
149  fs.close();
150 
151  fp = fopen(*path, "r+");
152  if(!fp)
153  shell::errexit(1, "*** sippasswd: cannot access digest");
154 
155  for(;;) {
156  fgetpos(fp, &pos);
157  if(NULL == fgets(buffer, sizeof(buffer), fp) || feof(fp))
158  break;
159 
160  if(String::equal(buffer, replace)) {
161  fclose(fp);
162  printf("digest unchanged\n");
163  exit(0);
164  }
165 
166  cp = strchr(buffer, ':');
167  if(!cp)
168  continue;
169 
170  *cp = 0;
171  if(String::equal(buffer, user))
172  break;
173  }
174 
175  // update digest file
176  fsetpos(fp, &pos);
177  fputs(replace, fp);
178  fclose(fp);
179 
180  // if server is up, also sync server with digest change...
181  fp = fopen(control, "w");
182  if(fp) {
183  fprintf(fp, "digest %s %s\n", user, *digestbuf);
184  fclose(fp);
185  }
186 
187  printf("digest updated\n");
188  PROGRAM_EXIT(0);
189 }
190 
Server control interfaces and functions.
Definition: control.h:58
Top level include directory for GNU Telephony SIP Witch Server.
short argc
Definition: cgiserver.cpp:93
PROGRAM_MAIN(argc, argv)
Definition: sippasswd.cpp:50