]> git.saurik.com Git - apt.git/blame - apt-pkg/contrib/netrc.cc
merged from donkult
[apt.git] / apt-pkg / contrib / netrc.cc
CommitLineData
592b7800
MV
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
3// $Id: netrc.c,v 1.38 2007-11-07 09:21:35 bagder Exp $
4/* ######################################################################
5
6 netrc file parser - returns the login and password of a give host in
7 a specified netrc-type file
8
9 Originally written by Daniel Stenberg, <daniel@haxx.se>, et al. and
10 placed into the Public Domain, do with it what you will.
11
12 ##################################################################### */
13 /*}}}*/
ea542140 14#include <config.h>
592b7800 15
f1c081b6 16#include <apt-pkg/configuration.h>
472ff00e 17#include <apt-pkg/strutl.h>
01fc8930 18#include <apt-pkg/fileutl.h>
472ff00e 19
592b7800
MV
20#include <iostream>
21#include <stdio.h>
22#include <stdlib.h>
23#include <string.h>
24#include <unistd.h>
25#include <pwd.h>
26
27#include "netrc.h"
28
8f3ba4e8 29using std::string;
592b7800
MV
30
31/* Get user and password from .netrc when given a machine name */
32
33enum {
34 NOTHING,
35 HOSTFOUND, /* the 'machine' keyword was found */
36 HOSTCOMPLETE, /* the machine name following the keyword was found too */
37 HOSTVALID, /* this is "our" machine! */
38 HOSTEND /* LAST enum */
39};
40
41/* make sure we have room for at least this size: */
42#define LOGINSIZE 64
43#define PASSWORDSIZE 64
44#define NETRC DOT_CHAR "netrc"
45
46/* returns -1 on failure, 0 if the host is found, 1 is the host isn't found */
47int parsenetrc (char *host, char *login, char *password, char *netrcfile = NULL)
48{
49 FILE *file;
50 int retcode = 1;
51 int specific_login = (login[0] != 0);
52 char *home = NULL;
53 bool netrc_alloc = false;
592b7800 54
592b7800
MV
55 int state_our_login = false; /* With specific_login,
56 found *our* login name */
57
58 if (!netrcfile) {
59 home = getenv ("HOME"); /* portable environment reader */
60
61 if (!home) {
62 struct passwd *pw;
63 pw = getpwuid (geteuid ());
64 if(pw)
65 home = pw->pw_dir;
66 }
67
68 if (!home)
69 return -1;
70
71 asprintf (&netrcfile, "%s%s%s", home, DIR_CHAR, NETRC);
72 if(!netrcfile)
73 return -1;
74 else
75 netrc_alloc = true;
76 }
77
78 file = fopen (netrcfile, "r");
79 if(file) {
80 char *tok;
81 char *tok_buf;
82 bool done = false;
83 char netrcbuffer[256];
84
91c03d37
DK
85 int state = NOTHING;
86 char state_login = 0; /* Found a login keyword */
87 char state_password = 0; /* Found a password keyword */
88
592b7800
MV
89 while (!done && fgets(netrcbuffer, sizeof (netrcbuffer), file)) {
90 tok = strtok_r (netrcbuffer, " \t\n", &tok_buf);
91 while (!done && tok) {
92 if(login[0] && password[0]) {
93 done = true;
94 break;
95 }
96
97 switch(state) {
98 case NOTHING:
99 if (!strcasecmp ("machine", tok)) {
100 /* the next tok is the machine name, this is in itself the
101 delimiter that starts the stuff entered for this machine,
102 after this we need to search for 'login' and
103 'password'. */
104 state = HOSTFOUND;
105 }
106 break;
107 case HOSTFOUND:
278835da
MV
108 /* extended definition of a "machine" if we have a "/"
109 we match the start of the string (host.startswith(token) */
110 if ((strchr(host, '/') && strstr(host, tok) == host) ||
111 (!strcasecmp (host, tok))) {
592b7800
MV
112 /* and yes, this is our host! */
113 state = HOSTVALID;
114 retcode = 0; /* we did find our host */
115 }
116 else
117 /* not our host */
118 state = NOTHING;
119 break;
120 case HOSTVALID:
121 /* we are now parsing sub-keywords concerning "our" host */
122 if (state_login) {
123 if (specific_login)
124 state_our_login = !strcasecmp (login, tok);
125 else
126 strncpy (login, tok, LOGINSIZE - 1);
127 state_login = 0;
128 } else if (state_password) {
129 if (state_our_login || !specific_login)
130 strncpy (password, tok, PASSWORDSIZE - 1);
131 state_password = 0;
132 } else if (!strcasecmp ("login", tok))
133 state_login = 1;
134 else if (!strcasecmp ("password", tok))
135 state_password = 1;
136 else if(!strcasecmp ("machine", tok)) {
137 /* ok, there's machine here go => */
138 state = HOSTFOUND;
139 state_our_login = false;
140 }
141 break;
142 } /* switch (state) */
143
144 tok = strtok_r (NULL, " \t\n", &tok_buf);
145 } /* while(tok) */
146 } /* while fgets() */
147
148 fclose(file);
149 }
150
151 if (netrc_alloc)
152 free(netrcfile);
153
154 return retcode;
155}
156
157void maybe_add_auth (URI &Uri, string NetRCFile)
158{
f1c081b6 159 if (_config->FindB("Debug::Acquire::netrc", false) == true)
01fc8930
MV
160 std::clog << "maybe_add_auth: " << (string)Uri
161 << " " << NetRCFile << std::endl;
f1c081b6 162 if (Uri.Password.empty () == true || Uri.User.empty () == true)
592b7800
MV
163 {
164 if (NetRCFile.empty () == false)
165 {
166 char login[64] = "";
167 char password[64] = "";
fc3eb5b2 168 char *netrcfile = strdup(NetRCFile.c_str());
592b7800 169
01fc8930 170 // first check for a generic host based netrc entry
fc3eb5b2 171 char *host = strdup(Uri.Host.c_str());
01fc8930 172 if (host && parsenetrc (host, login, password, netrcfile) == 0)
592b7800 173 {
01fc8930
MV
174 if (_config->FindB("Debug::Acquire::netrc", false) == true)
175 std::clog << "host: " << host
176 << " user: " << login
177 << " pass-size: " << strlen(password)
178 << std::endl;
592b7800
MV
179 Uri.User = string (login);
180 Uri.Password = string (password);
fc3eb5b2
DK
181 free(netrcfile);
182 free(host);
01fc8930 183 return;
592b7800 184 }
fc3eb5b2 185 free(host);
592b7800 186
278835da
MV
187 // if host did not work, try Host+Path next, this will trigger
188 // a lookup uri.startswith(host) in the netrc file parser (because
189 // of the "/"
fc3eb5b2 190 char *hostpath = strdup(string(Uri.Host+Uri.Path).c_str());
01fc8930
MV
191 if (hostpath && parsenetrc (hostpath, login, password, netrcfile) == 0)
192 {
193 if (_config->FindB("Debug::Acquire::netrc", false) == true)
194 std::clog << "hostpath: " << hostpath
195 << " user: " << login
196 << " pass-size: " << strlen(password)
197 << std::endl;
198 Uri.User = string (login);
199 Uri.Password = string (password);
01fc8930 200 }
fc3eb5b2
DK
201 free(netrcfile);
202 free(hostpath);
592b7800
MV
203 }
204 }
205}
206
207#ifdef DEBUG
208int main(int argc, char* argv[])
209{
210 char login[64] = "";
211 char password[64] = "";
212
213 if(argc < 2)
214 return -1;
215
216 if(0 == parsenetrc (argv[1], login, password, argv[2])) {
217 printf("HOST: %s LOGIN: %s PASSWORD: %s\n", argv[1], login, password);
218 }
219}
220#endif